2-1 你知道应用进程是怎么启动的吗?
(1) Linux下进程启动的方式
pid=fork(),这个方法会返回2次。pid为0时在子进程执行,pid为子进程的进程id时,在父进程执行。若在子进程中,没有execve(path, argv, env)函数,则子进程共享父进程的资源;如执行了此函数,则path会替换父进程的资源,即不与父进程共享。
(2) 应用进程启动的基本流程
什么时候触发的进程启动?
答:被动启动,启动组件的时候,判断进程是否启动,若未启动,则先启动进程。
谁发起的?
答:由AMS向zygote发起的,通过socket通信,将要启动的类名ActivityThread和方法名main发送给zygote.
进程是谁启动的?怎么启动的?
答:zygote fork出应用进程,会去执行入口函数,即ActivityThread的main函数。应用进程启动之后向AMS报告,将applicationThread注册到AMS,整个启动才算结束。
2-2 应用是怎么启用Binder机制的?
了解binder是用来干什么的? 答:跨进程通信
应用里面哪些地方用到了binder机制?答:启动组件(如:activity,service,广播)
应用的大致启动流程是怎样的? 答:AMS请求zygote,zygote启动应用,应用告诉AMS它已经启动了。
一个进程是怎么启用binder机制的?
答:binder机制是在zygote启动应用的过程中启动。zygote的runOnce()函数中 =》获取参数 =》for应用 =》在子进程执行handleChildProc() =》zygoteInit() =》后续步骤同2-3(3)启用binder机制:打开binder驱动;映射内存,分配缓冲区;启动binder线程,进入binder loop。
2-3 谈谈你对Application的理解
(1) Application的作用(初级)
答:1.保存应用进程内的全局变量(生命周期长);2.初始化操作(启动早);3.提供应用上下文。
(2) Application的类继承关系以及生命周期(中级)
答:继承关系:Application继承自ContextWrapper,ContextWrapper继承Context,ContextWrapper类包装了Context,在其中有个成员变量Context mBase,mBase通过构造函数或者attachBaseContext()方法赋值初始化(典型的静态代理)。
生命周期:启动和结束。启动包括:构造函数;attachBaseContext;onCreate。
(3) Application的初始化原理(高级)
ActivityThread的main() =》 ActivityThread thread = new ActivityThread();thread.attach(false);
=》ActivityManagerNative.getDefault().attachApplication(mAppThread)这里是跨进程binder调用
=》在AMS中attachApplication() => attachApplicationLocked(thread, callingPid);
=》thread.bindApplication(...) 跨进程binder调用 => 在应用进程中,bindApplication()
=》封装参数到 AppBindData data,sendMessage(H.BIND_APPLICATION, data),即发送消息到主线程
=》handleBindApplication(AppBindData data)
=》先获取应用安装包信息(LoadedApk类),然后makeApplication(...)
=》构建ContextImpl context,newApplication(...)
=》newApplication(cl.loadClass(className), context);
=》Application app = (Application)clazz.newInstance();app.attach(context);
=》callApplicationOnCreate(app),即application的onCreate()方法。
(4) 不要在application的onCreate()方法中执行耗时操作,为什么?
在attachApplicationLocked(IApplicationThread thread,...)方法中,这里是在主线程执行的。
boolean attachApplicationLocked(IApplicationThread thread,...) {
thread.bindApplication(...);//oneway,即向AMS发送请求后,不用等处理完马上返回,这里并不会阻塞主线程
...
mStackSupervisor.attachApplicationLocked(...);//Activity组件的启动
mServices.attachApplicationLocked(app, processName);//Service组件的启动
sendPendingBroadcastsLocked(app);//广播的启动
}
从上面可以看出,onCreate()方法中执行耗时操作,不会阻塞AMS,但会延迟应用组件的启动。
2-4 谈谈你对Context的理解
Context的作用:应用组件的上下文,有了上下文,组件就可以访问资源和调用系统服务。
(1) 应用里面有多少个Context?不同的Context之间有什么区别?
答:activity的个数 + service的个数 + application的个数(单进程只有1个实例)。广播和Content Provider并没有继承context。activity因为要显示UI,是继承了ContextThemeWraper,而application和service是继承了ContextWraper.
(2) Activity里的this和getBaseContext有什么区别?
答: this是指Activity对象自己,getBaseContext是指Context里的成员变量Context mBase.
(3) getApplication和getApplicationContext有什么区别?
答:都是返回application对象。getApplicationContext是Context里的一个抽象方法,getApplication只有activity和service里特有的。
(4) 应用组件的构造,onCreate、attachBaseContext调用顺序?
答:应用组件的构造方法 -> attachBaseContext -> onCreate.