关键类说明
整个启动流程因为会涉及到多次Binder通信,这里先简要说明一下几个类的用途,方便大家理解整个交互流程:
- ActivityManagerService :AMS是Android中最核心的服务之一,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,其职责与操作系统中的进程管理和调度模块相类似,因此它在Android中非常重要,它本身也是一个Binder的实现类。
- Instrumentation :顾名思义,它用来监控应用程序和系统的交互。
- ActivityThread :应用的入口类,系统通过调用main函数,开启消息循环队列。ActivityThread所在线程被称为应用的主线程(UI线程)。
- ApplicationThread :ApplicationThread提供Binder通讯接口,AMS则通过代理调用此App进程的本地方法。
- ActivityManagerProxy :AMS服务在当前进程的代理类,负责与AMS通信。
- ApplicationThreadProxy :ApplicationThread在AMS服务中的代理类,负责与ApplicationThread通信。
流程分析
1、Launcher响应用户点击,通知AMS
Launcher做为应用的入口,通过starActicity辗转调用到Activity:startActivityForResult而后则调用至Instrumentation:execStartActivity。在Instrumentation:execStartActivity方法中,这里的 ActivityManagerNative.getDefault 返回ActivityManagerService的远程接口,即 ActivityManagerProxy 接口,通过Binder驱动程序, ActivityManagerProxy 与AMS服务通信,则实现了跨进程到System进程。
2、AMS响应Launcher进程请求
从上面的流程我们知道,此时AMS应该处理Launcher进程发来的请求,请参看时序图及源码,此时我们调用到ActivityStackSupervisor:startActivityUncheckedLocked方法。在这个方法中函数经过intent的标志值设置,通过findTaskLocked函数来查找存不存这样的Task,这里返回的结果是null,即intentActivity为null,因此,需要创建一个新的Task来启动这个Activity。现在处理堆栈顶端的Activity是Launcher,与我们即将要启动的MainActivity不是同一个Activity,创建了一个新的Task里面来启动这个Activity。经过栈顶检测,则需要将Launcher推入Paused状态,才可以启动新的Activity。后续则调用至ActivityStack:startPausingLocked,在这个函数中的prev.app.thread是一个ApplicationThread对象的远程接口,通过调用这个远程接口的schedulePauseActivity来通知Launcher进入Paused状态。至此,AMS对Launcher的请求已经响应,这是我们发现又通过Binder通信回调至Launcher进程。
3、Launcher进程挂起Launcher,再次通知AMS
这个流程相对会简单一些,我们来看Launcher中的ActivityThread,这部分Launcher的ActivityThread处理页面Paused并且再次通过ActivityManagerProxy通知AMS。
4、AMS创建新的进程
创建新进程的时候,AMS会保存一个ProcessRecord信息,如果应用程序中的AndroidManifest.xml配置文件中,我们没有指定Application标签的process属性,系统就会默认使用package的名称。每一个应用程序都有自己的uid,因此,这里uid + process的组合就可以为每一个应用程序创建一个ProcessRecord。这里主要是调用Process:start接口来创建一个新的进程,新的进程会导入android.app.ActivityThread类,并且执行它的main函数,这就是每一个应用程序都有一个ActivityThread实例来对应的原因。
5、应用进程初始化
我们来看Activity的main函数,这里绑定了主线程的Looper,并进入消息循环,大家应该知道,整个Android系统是消息驱动的,这也是为什么主线程默认绑定Looper的原因。attach函数最终调用了ActivityManagerService的远程接口ActivityManagerProxy的attachApplication函数,传入的参数是mAppThread,这是一个ApplicationThread类型的Binder对象,它的作用是AMS与应用进程进行进程间通信的。
6、在AMS中注册应用进程,启动启动栈顶页面
前面我们提到了AMS负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,通过上一个流程我们知道应用进程创建后通过Binder驱动与AMS产生交互,此时AMS则将应用进程创建后的信息进行了一次 注册 ,如果拿Windows系统程序注册到的注册表来理解这个过程,可能会更形象一些。mMainStack.topRunningActivityLocked(null)从堆栈顶端取出要启动的Activity,并在realStartActivityLockedhan函数中通过ApplicationThreadProxy调回App进程启动页面。此时在App进程,我们可以看到,经过一些列的调用链最终调用至MainActivity:onCreate函数,之后会调用至onResume,而后会通知AMS该MainActivity已经处于resume状态。至此,整个启动流程告一段落。
详细的启动流程分析
以被启动应用的角度看整个流程
详细分析(个人感觉没有时序来的容易理解)
补充知识 APP启动方式
通常来说,APP中启动方式分为两种:冷启动和热启动。
- 冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动。
- 热启动:当启动应用时,后台已有该应用的进程(例:按back键/home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动应用,这个方式叫热启动。
请注意:上面说的启动是点击app的启动图标来启动的,而另外一种方式是进入最近使用的列表界面来启动应用,这种不应该叫启动,应该叫恢复。