在移动应用开发中,Android四大组件之一Activity是最常用的。很多界面,如:闪屏、主界面、次功能界面等都需要Activity来作为主要的载体;界面与界面之间,即不同的Activity之间也都存在跳转切换,弄懂这其中跳转切换原理,将有助于我们更好的理解Android中Activity之间的交互逻辑,从而更好的开发Android应用。本篇博文将会重点介绍Android应用中的Activity的启动流程。
在开始介绍之前,我们需要了解一些概念,如:
- ActivityThread: 应用的启动入口类,当应用启动,会首先执行其main方法,开启主线程消息循环机制。
- ApplicationThread: ActivityThread的内部类,主要与系统进程AMS通信,从而对应用进程的具体Activity操作进行管理。
- Instrumentation: ActivityThread的属性变量,主要辅助ActivityThread类调用Activity的生命周期相关方法。
- ActivityManagerService(AMS): Activity管理系统服务类,主要是对所有的Activity进行管理。
- ActivityStack: Activity任务栈,AMS的属性变量,AMS中Activtiy的实际管理者。
一、Activity启动流程
此流程图,主要是根据Android源码中代码执行顺序来梳理的。浅绿色部分为应用进程,浅蓝色部分为系统服务进程,两个进程间通过Binder驱动来进行通信,第一次Binder通信主要的类有:ActivityManagerService(AMS),ActivityManagerNative(AMN),ActivityManagerProxy(AMP);第二次Binder通信主要的类有:ApplicationThread(AT),ApplicationThreadNative(ATN),ApplicationThreadProxy(ATP)。
二、Activity启动流程源码分析
根据上面流程图,下面让我们一起来看看源码,首先从Activity的startActivity开始:
在Activity源码中,startActivity之后都会调用startActivityForResult;在注释1处,当mParent为空时,会直接调用Instrumentation中的execStartActivity方法,当mParent不为空时,调用mParent.startActivityFromChild方法。通过跟踪查找发现,mParent也是Activity,在Activity attach的时候会初始化,从ActivityRecord中获得值。我们继续来看看startActivityFromChild方法
由此发现,startActivityForResult之后都调用了Instrumentation中的execStartActivity方法。我们继续来看看execStartActivity方法:
这里主要是调用了ActivityManagerNative.getDefault()中的startActivity(…)方法,这里就涉及到Binder的一次跨进程通信,通过跨进程通信调用了ActivityManagerService中的startActivity方法。具体Binder怎么跨进程通信的,我已写过文章 Android跨进程通信方式(IPC)解析,想了解的同学,可以点击看看。下面我们继续来看看AMS中的startActivity方法:
在AMS的startActivity方法中,又调用ActivityStack中的startActivityMayWait()方法,我们再来看看ActivityStack的源码:
我们这里主要分析启动流程,所以省略掉部分细节。让我们继续看ActivityStack中的startActivityLocked()方法
同上,也省略的部分细节。我们继续
在startActivityUncheckedLocked()方法中,主要针对Activity的启动模式进行了检测判断,从而启动Activity。我们知道,Activity有四种启动模式,分别为standard,singleTop,singleTask和singleInstance,但这里我们主要是分析Activity的启动流程,所以具体启动模式的判断逻辑细节,这里就不展开分析了。我们主要来看一下,把Activity启动放到栈顶的方法resumeTopActivityLocked()
通过上面注释中的分析,在判断Activity进程之后,就会通过startSpecificActivityLocked()方法来启动Activity,我们继续看
在startSpecificActivityLocked()方法中也对Activity的进程是否存在做了判断,当进程存在时直接调用realStartActivityLocked()方法启动Activity;当Activity的进程不存在时,就会调用AMS的startProcessLocked()方法创建进程,这里其实是Activity的另一种启动流程,从Laucher启动,只有从Launcher启动才会没有进程,这里先不做深度分析,后续我们针对Activity的Launcher启动再写一篇博文。已补博文Activity启动流程源码分析(Launcher中)。下面让我们继续看realStartActivityLocked()方法:
这里主要通过调用app.thread.scheduleLaunchActivity(…)方法实现了跨进程通信,这里主要实现了流程图中的第二次Binder跨进程通信。通过Binder跨进程通信调用了ApplicationThread中的scheduleLaunchActivity(…)方法,具体Binder怎么跨进程通信的,我已写过文章 Android跨进程通信方式(IPC)解析,想了解的同学,可以点击看看。下面我们继续来看看ApplicationThread中的scheduleLaunchActivity方法:
由上易知,通过Handler消息循环机制,从而执行handleLaunchActivity()方法,我们继续来看此方法
注释1处,通过mInstrumentation.newActivity()方法对Activity进行初始化
由上我们知道,主要通过反射机制实现Activity的初始化。再来看注释2,调用了Activity.attach(…)方法
此方法主要就是对Activity进行了初始化,初始化了许多的属性,具体如上。我们再看注释3,方法mInstrumentation.callActivityOnCreate(activity, r.state),我们也来看看源码
其实,主要也就是调用了Activity的OnCreate()方法,我们继续来看看
的确如此,最后调用了Activity的OnCreate方法,从而就启动了Activity。好了,到这里,Activity的启动流程就说完了。
注:源码采用android-4.1.1_r1版本,建议下载源码然后自己走一遍流程,这样更能加深理解。