前言
这次主要是从源码角度和IPC角度分析下Activity的启动流程,基于Android 8.0,估计知识点比较多0.0,而且需要提前了解下一丢丢IPC的东西。
铺垫
首先,从用户点击APP图标开始走起。既然是启动一个APP,那必然需要启动一个进程来执行App。因为Android是基于Linux的,所有的进程都是由init进程fork出来的。所以(1)当手机系统启动的时候,init进程会创建一个Zygote进程,后面我们所有app的进程都是由这个Zygote进程fork出来的;(2)当有app启动时,ActivityManagerService会通过socket通知Zygote进程fork一个新进程。在这里额外说明一哈,其实这个AMS也是通过Zygote创建的,Zygote进程创建后首先会创建一个SystemServer进程,在这个SS进程中会启动像AMS、PMS这样的服务,有的都是IPC中关键的服务端程序。所以Zygote进程和SystemServer进程是Android Framework中非常重要的两大进程。
上面说到了app的进程是由Zygote孵化出来的,那么究竟是哪个进程去通知孵化的。其实很简单,如果是从其他app中启动的,就是那个app所在的进程;如果是从桌面启动的就是launcher进程,Launcher其实也是继承自Activity,所以我们也可以把桌面当作一个app,两种启动的方式都是调用startActivity()发送intent请求。
那么……敌军还有5秒到达战场……重要的来了
Activity(C端)
我们通常调用的startActivity的几种重载方法最终都会调用startActivityForResult()方法
|
|
主要看当mParent为null时,这个mParent指的是ActivityGroup,用来嵌套多个Activity,不过这个现在已经被废弃了,都用fragment来代替了,这里提主要是为了提醒下startActivityFromChild()这个方法,也能启动activity(记得在笔试题见到过 = =、)。好了回归主线,启动Activity的任务会交给Instrumention的execStartActivity()方法,注意这里的一个参数 mMainThread.getApplicationThread(),很重要,先记住。
|
|
首先来说说Instrumention这个类,每个Activity都持有Instrumentation对象的一个引用,但是整个进程只会存在一个Instrumentation对象,Instrumentation充当着一个管家的作用,任何和activity生命周期包括创建相关的方法都是通过它来具体实现的,这些后面再说它。
在execStartActivity()中,通过ActivityManager启动activity,ActivityManager.getService()返回的是一个单例,这个单例通过 asInterface()方法返回了一个Proxy对象,Proxy对象实现了IActivityManager接口,里面保存着服务端的binder对象(这个对象是通过ServiceManager拿到服务端的AMS binder对象),所以最后会通过Binder跨进程去调用服务端AMS中的方法启动activity。这其实就是个aidl的模板,可以自己敲一个aidl的实例对照着分析。
注意: 在8.0的时候,这里直接采用了aidl进行cs通信,所以8.0以前的ActivityManagerNative(服务端)、ActivityManagerProxy(客户端)已经被废弃,没有之前那么复杂了,但是原理都是一样的,最后都会跨进程去通知服务端的AMS启动activity。只不过8.0之前是通过binder(ActivityManagerNative)的transact()方法将数据打包成Parcel对象传给服务端,具体的流程大家可以自己去查阅,现在市面上的分析大部分都是8.0之前的版本。
AMS(S端)
现在启动任务交给了核心服务AMS处理:
为了方便看到流程,我把详细参数都省略掉了,可以看到最后会交给ActivityStarter去启动:
其实,ActivityStarter类中的逻辑像是在做战斗前的准备工作,比如确认战斗的双方、战斗的目标和战斗时间等等。在startActivityMayWait()方法中主要获取调用者的uid和pid,并且通过resolveIntent和resolveActivity获取ActivityInfo信息,确定要启动的Activity组件;在startActivityLocked()方法中去调用startActivity()创建ActivityRecord,记录activity的核心状态信息;在startActivityUnchecked()方法中根据intent的Flag信息、activity的启动模式分配或者创建任务栈,设置TaskRecord。最后去调用ActivityStackSupervisor和ActivityStack中的相关方法:
可以看到上面的代码是绕来绕去,= =、我们知道activity都是通过任务栈来进行管理的,所以stackSupervisor就是服务端统一管理这些任务栈的地方,而ActivityStack就是用来管理当前任务栈中的activity,所以服务端干的事简单来说就是完成activity的切换、将要启动的activity移至栈顶,然后通知客户端去渲染ui。但是实际上里面的逻辑很复杂,比如说不同启动模式下,栈中的activity如何操作,以及我们常见的为什么是firstActivity onPause之后secondActivity 才开始创建等等,这些和任务栈相关的都是在服务端控制。
里面具体的逻辑这里就不分析了,我们主要分析这个启动流程,参考下图了解下即可。
重点是最后这个realstart方法中的这句scheduleLaunchActivity,其他之前的包括starter中的逻辑都是在铺垫。。这个app.thread其实是保存在ProcessRecord中的一个IApplicationThread对象,是不是感觉这个对象名字很熟悉,它其实就是客户端中的ApplicationThread,因为从AMS开始,方法的执行都是在服务端执行,所以服务端的工作做完了,就需要去通知客户端去操作了,那么通知的桥梁就是这个ApplicationThread对象,它继承自IApplicationThread.Stub,是一个binder对象,其实这里跟上面和AMS的通信一样,在8.0之后,统一采用aidl方式,放弃了像ApplicationThreadNative+ApplicationThreadProxy的方式,但是它们的作用和aidl生成的java类中的逻辑是一样的,这个大家手动敲一个aidl的例子对比一哈就能看出来。
回到主线程
下面我们就具体看看客户端后续在干什么:
|
|
这里activity启动之后将消息传递给activitythread中的handler处理,然后重点在消息处理后调用的performLaunchActivity中,主要干了两件事,一是通过反射创建activity,二是创建application,当然如果application已存在,就不用再创建了。后面就开始了Activity生命周期的调用。
在performLaunchActivity方法中可以看到,调用生命周期oncreate方法的具体实现是在mInstrumentation中,其实其他像activity和Application的生命周期的调用包括创建等等也是在这个类中实现,所以就印证了我上面提到的Instrumentation充当着一个管家的作用。
到这里,,就差不多可以点投降了。
这里简单的总结了下启动过程中的ipc,当然这里面不仅仅只有这两次跨进程通信,而且服务端参与的服务也不仅仅只有AMS,像在resolveIntent时就会跨进程去调用PMS中的服务。
那么Activity启动的流程….大致…..是这样,猝。