App启动流程分析
前言
上一篇文章中我分析了Activity的启动流程,是建立在App进程已经创建完成(即App已经打开)的情况下的,那么App从点击图标到启动Activity这个过程是怎么样的呢,本文就来简单分析一下。
源码分析
首先还是先强调一下,本文的分析基于Android 9.0(API Level 28)的源码。
Android系统的桌面其实就是一个App,这个特殊的App叫做Launcher,很多手机生产厂商都有自己定制的Launcher,因此不同的手机桌面样式会有些许的不同。目前Android原生的Launcher版本是Launcher3,而我们桌面上所展示的Activity的就是Launcher3中的Launcher.java
,在这个Activity中展示着手机上安装的应用程序快捷方式,它的定义如下:
Launcher.java
1 | public class Launcher extends BaseDraggingActivity implements LauncherExterns, |
Launcher中声明了一个createShortcut()
方法,从方法名也能猜到是用来创建应用快捷方式(图标)的。
1 | public View createShortcut(ViewGroup parent, ShortcutInfo info) { |
由于我们要研究App的启动流程,因此首先要从点击图标的方法来入手,可以看出点击事件定义在了ItemClickHandler类中,我们来看一下:
ItemClickHandler.java
1 | public class ItemClickHandler { |
ItemClickHandler的onClick()
方法判断了如果点击的是应用快捷方式就调用onClickAppShortcut()
方法,接着又调用了startAppShortcutOrInfoActivity()
方法,最后会调用Launcher的startActivitySafely()
方法。
1 | public boolean startActivitySafely(View v, Intent intent, ItemInfo item) { |
该方法又调用了父类BaseDraggingActivity的startActivitySafely()
方法:
1 | public boolean startActivitySafely(View v, Intent intent, ItemInfo item) { |
可以看到startActivitySafely()
方法最终调用了startActivity()
方法,并设置了FLAG_ACTIVITY_NEW_TASK这个Flag,不难理解,启动一个App肯定是要创建一个新的Activity任务栈的。
到这里就又回到了Activity的startActivity()
方法,也就是Activity的启动流程,这一部分我就不从头开始分析了了,可以查看上一篇文章Activity启动流程,这里附上Activity启动的流程图。
我们跳过一部分流程,直接来看ActivityStackSupervisor的startSpecificActivityLocked()
方法:
1 | void startSpecificActivityLocked(ActivityRecord r, |
在Activity的启动流程分析中,我直接默认为App进程已创建,这里就要分析另一种情况了,也就是应用进程未创建,这种情况会执行mService.startProcessLocked()
方法,mService的类型是ActivityManagerService(AMS),我们来看ActivityManagerService的startProcessLocked()
方法:
1 | final ProcessRecord startProcessLocked(String processName, |
经过一系列调用最终执行了Process.start()
方法:
1 | public static final ProcessStartResult start(final String processClass, |
接着又调用了ZygoteProcess的start()
方法:
1 | public final Process.ProcessStartResult start(final String processClass, |
这里又是经过了一系列的调用,最终执行了zygoteSendArgsAndGetResult()
方法,该方法的作用就是创建App进程。关于App进程的创建,我粗略地阅读了一下网上的相关文章,简单介绍一下,Android中有一个重要的进程Zygote,翻译为受精卵进程,所有的应用程序进程都是通过Zygote进程fork得来的。流程简单来说就是通过Binder请求AMS进程,然后AMS再发送Socket消息给Zygote进程,最后统一由Zygote进程fork出应用进程。由于应用程序进程的创建涉及到了Android的一些底层原理,包括Linux的一些知识,目前我也不能说得很清楚,因此就简单介绍一下,感兴趣的话自行查阅资料吧,这里附上一张Gityuan大神绘制的的流程图。
进程创建完成后,就会执行ActivityThread的main()
方法,它是应用程序的入口方法(当然从应用进程创建到执行main()
方法这中间的过程还要更复杂,本文就不深入探讨了)。
1 | public static void main(String[] args) { |
main()
方法内部创建了主线程Looper并开启了消息循环,由于这不是本文的重点,就不多提了。此外,还创建了ActivityThread对象并调用了attach()
方法,我们接下来看一下这个方法。
1 | private void attach(boolean system, long startSeq) { |
这里省略了大量代码,核心代码就是调用mgr.attachApplication()
方法,其中mgr是通过ActivityManager.getService()
得到的,因此就是ActivityManagerService对象,我们来看AMS的attachApplication()
方法:
1 |
|
attachApplication()
方法内部又调用了attachApplicationLocked()
方法:
1 | private final boolean attachApplicationLocked(IApplicationThread thread, |
这里省略了大量代码,attachApplicationLocked()
内部主要调用了两个关键方法:第一个是thread.bindApplication()
;第二个是mStackSupervisor.attachApplicationLocked(app)
,下面我们就分别来看一下这两个方法都做了什么。
thread.bindApplication()
方法
这里的thread即上面调用ActivityThread的attach()
方法传过来的mAppThread,它的类型为ApplicationThread,我们来看一下ApplicationThread的bindApplication()
方法:
1 | public final void bindApplication(String processName, ApplicationInfo appInfo, |
可以看到方法最后调用了我们熟悉的sendMessage()
方法,接下来找到H的handleMessage()
方法对BIND_APPLICATION消息的处理。
1 | public void handleMessage(Message msg) { |
接着调用了handleBindApplication()
方法:
1 | private void handleBindApplication(AppBindData data) { |
方法内部创建了Instrumentation实例对象,最后调用了data.info.makeApplication()
方法,data.info的类型为LoadedApk,makeApplication()
方法在Activity的启动流程分析中也提到过,是通过类加载器创建Application对象,并且可以保证只有一个Application实例,这里就不展示了。
因此bindApplication()
方法的目的就是创建Application实例对象。
mStackSupervisor.attachApplicationLocked(app)
方法
mStackSupervisor的类型为ActivityStackSupervisor,我们来看ActivityStackSupervisor的attachApplicationLocked()
方法:
1 | boolean attachApplicationLocked(ProcessRecord app) throws RemoteException { |
attachApplicationLocked()
方法内部调用了realStartActivityLocked()
方法,这个方法我们可能有点印象,在Activity的启动流程中也有分析到该方法,我们再来简单回顾一下。
1 | final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, |
接下来的流程就和Activity的启动相同了,最终通过发送消息依次调用ActivityThread的handleLaunchActivity()
方法和performLaunchActivity()
方法,完成Activity的创建等工作,回调Activity的onCreate()
生命周期方法,就不再重复分析了。
分析到这里,App的简单启动流程我们就清楚了,基本上和Activity的启动流程类似,不同之处是需要创建应用进程,一个简单的流程图如下所示:
总结
分析过Activity的启动流程后再来看App的启动流程会简单很多,因为有很多流程是相同的,本质上来开还是启动一个新的Activity,区别主要就在于需要创建应用进程,限于自身水平原因,这部分我也没有详细分析,有兴趣的话还是可以了解一下的。