Activity的启动流程是一个资深Android工程师必须掌握的内容,也是高职级面试中的高频面试知识点,无论是从事应用层开发,还是Framework开发,其重要性都无需我多言。而要真正理解它,就不可避免地要深入到源码了,本文将从Android8.1系统源码入手,来抽丝剥茧。由于Activity的启动流程涉及到的细节非常多而且复杂,为了便于读理解,本文将摒弃众多的细节,而着重于关键流程的梳理。

       尽管简化了很多细节,但流程还是不少,为了便于读者阅读和理解,笔者会先给出重要的结论和UML序列图,读者正确的阅读方式也是先知道梗概,再结合UML序列图来看源码,同时最好能自己再IDE上打开源码,顺着笔者的思路去阅读,否者会看得晕头转向。

       本文主要包含如下内容

【系统之音】Android系统启动篇-LMLPHP

1、启动Activity的若干场景

       Activity的启动有多种途径,比较常见的有:

    (1)点击Launcher中的快捷图标,这种方式进入的是根Activity;

    (2)从其它应用跳转到某个应用的activity,这种场景下启动的可以是根Activity,也可以是其它Activity,如:从某些应用拨打电话、开启相机、打开浏览器等;

    (3)同一个应用种从某个组件中启动Activity。

      而启动某个Activity的时候,也可能有两种情形:

    (1)目标Activity所在应用程序进程不存在,也就是此时该应用还没有启动的情形;

    (2)目标Activity所在应用程序进程存在,也就是该应用之前启动过。

      上面这些场景,Activity的启动流程肯定是存在一定差异的,但核心流程基本一致,都是在基本流程基础上或增或减部分流程。从Launcher中点击快捷图标启动一个根Activity的场景,就比较有代表性,本文将以此情形来介绍Activity的启动流程。

2、根Activity启动流程概貌

       这里,我先给出结论,读者们先宏观看看这其中大概有哪几步。先上图:

【系统之音】Android系统启动篇-LMLPHP

       从Launcher中点击快捷图标到启动根Activity过程中,主要涉及到4个进程的交互:Launcher所在应用进程、ActivityManagerService(后文简称AMS)所在的SystemServe系统进程、Zygote系统进程、目标根Activity所在的应用程序进程(这里请读者注意一下不同颜色所表示的不同进程,后文会与此保持一致)。

  (1)Launcher进程请求AMS创建根Activity。我们知道,在系统启动过程中,会启动SystemServer进程, AMS、PackageManagerService(后文简称PMS)也是在这个环节中启动的,所以AMS是运行在SystemServer进程当中的。应用的根Activity会在AndroidManifest.xml文件中注册,PMS解析出这些信息,并在Launcher中对这些包名、Activity路径及名称等信息进行封装,当点击快捷图标时,Launcher会调用startActivity方法去启动该图标所对应的根Activity。然后在Luancher进程中通过层层调用,直到通过Binder方式实现IPC,流程就进入到AMS中,也就是SystemServer进程中。

  (2)AMS请求创建根Activity所在的进程。AMS收到Launcher进程启动根Activity的请求后,会先判断根Activity所在的进程是否已经创建过了,如果没有创建过,则会向Zygote进程请求创建该进程,我们目前讨论的情形就是根Activity所在进程没有创建过的情况。我们知道,Zygote进程在启动的时候,会作为服务端创建一个名为“zygote”的Socket,用于监听AMS发起的创建新应用进程请求,所以此时流程进入到Zygote进程中。

  (3)Zygote进程fork出目标进程。Zygote收到AMS的请求后,会以fork的方式创建这个新的应用进程,此过程中会实例化一个ActivityThread对象,也就是一般所说的主线程,运行其入口main方法。

  (4)AMS调度应用进程创建和启动根Activity。根Activity所在的应用程序进程被创建后,AMS在SystemServer进程中也经过层层调用,最终又通过Binder方式实现IPC,将启动Activity的任务交给应用程序进程中的ApplicationThread本地代理,此后,流程进入到根Activity所在的应用程序进程中。这部分流程中,SystemServer中所做的工作主要是根Actifity创建和启动前的一些准备工作,比如当前用户权限等。

  (5)在应用进程中完成根Activity的创建和启动。在这里将创建根Activity实例、Applicaiton实例,调用各个生命周期方法,并将DecorView(布局文件中的View会添加到DecorView中)添加到Window中显示出来。 

       上文中涉及到系统启动流程相关知识,比如Zygote、SystemServer、AMS、PMS 的启动以及Zygote的功能,读者不清楚的画,最好先阅读这篇文章:【系统之音】Android系统启动篇

3、从Launcher到AMS

       先上UML序列图 

【系统之音】Android系统启动篇-LMLPHP

       前面说过,点击Luancher中的快捷图标的时候,会通过startActivity启动其对应的Activity,Launcher进程中的这部分流程源码如下:

       Launcher.java的源码路径:/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

 1 //==========Launcher.java========
 2 private void startAppShortcutOrInfoActivity(View v) {
 3      ......
 4      boolean success = startActivitySafely(v, intent, item);
 5      ......
 6 }
 7
 8 public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
 9      ......
10      startActivity(intent, optsBundle);
11      ......
12 }
13
14 //===========Activity.java========
15 /**
16  * Launch a new activity.
17  * ......
18  */
19 @Override
20 public void startActivity(Intent intent, @Nullable Bundle options) {
21     if (options != null) {
22         startActivityForResult(intent, -1, options);
23     } else {
24         ......
25         startActivityForResult(intent, -1);
26     }
27 }
28
29 public void startActivityForResult(...) {
30    if (mParent == null) { //表示当前根Activity还没有创建
31             ......
32             Instrumentation.ActivityResult ar =
33                 mInstrumentation.execStartActivity(
34                     this, mMainThread.getApplicationThread(), mToken, this,
35                     intent, requestCode, options);
36             ......
37         }
38 }
39
40 //===========Instrumentation.java==============
41 public ActivityResult execStartActivity(...){
42        ......
43        int result = ActivityManager.getService()
44                        .startActivity(whoThread, who.getBasePackageName(), intent,
45                                intent.resolveTypeIfNeeded(who.getContentResolver()),
46                                token, target != null ? target.mEmbeddedID : null,
47                                requestCode, 0, null, options); //代码①
48        ......
49 }

通过上述代码后,流程就从Launcher进程进入到AMS所在的SystemServer进程了, 这部分流程比较简单,这里就不做过多解释了。这里重点看一下代码①处(第43行)的ActivityManager.getService():

 1 //=========ActivityManager.java=========
 2 public static IActivityManager getService() {
 3     return IActivityManagerSingleton.get();
 4 }
 5 private static final Singleton<IActivityManager> IActivityManagerSingleton =
 6         new Singleton<IActivityManager>() {
 7             @Override
 8             protected IActivityManager create() {
 9                 final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
10                 final IActivityManager am = IActivityManager.Stub.asInterface(b);
11                 return am;
12             }
13         };
14
15 //=================Singleton.java=========
16 /**
17  * Singleton helper class for lazily initialization.
18  * ......
19  */
20 public abstract class Singleton<T> {
21     private T mInstance;
22
23     protected abstract T create();
24
25     public final T get() {
26         synchronized (this) {
27             if (mInstance == null) {
28                 mInstance = create();
29             }
30             return mInstance;
31         }
32     }
33 }

ActivityManager.getService()这句代码实际上就是通过单例模式获取AMS在Launcher进程中的远程代理,类似这样的代码实现在系统源码种还是比较常见的。

4、从AMS到应用程序进程

      先上UML序列图:

【系统之音】Android系统启动篇-LMLPHP

        这一部分的启动流程调用非常繁琐,可谓是“峰回路转”,笔者在跟进其调用流程时差点昏厥了,大有“山重水复疑无路”的困惑,直到看到下面代码:

1 final boolean realStartActivityLocked(...){
2       ......
3       app.thread.scheduleLaunchActivity(...); //代码②
4       ......
5 }

此时又深感“柳暗花明又一村”了。ApplicationThread是ActivityThread中的一个内部类,也是应用程序进程中的一个服务(Stub),通过Binder方式对外提供服务:

1 //=======ActivityThread.java======
2 private class ApplicationThread extends IApplicationThread.Stub {
3       ......
4       public final void scheduleLaunchActivity(...){
5             ......
6       }
7       ......
8 }

这里我们需要重点理解下图中的模型:

【系统之音】Android系统启动篇-LMLPHP

       每个应用程序都运行在一个独立的进程中(当然也可以声明为多个进程,这里不做讨论),不同进程之间内存等资源是不能直接共享的,只能通过Binder方式来和外界交互。这就好比系统像个大海,应用程序进程就像一座座孤岛,而Binder就是孤岛之间的桥梁或者船只。上图中模拟了应用程序进程与SystemServer进程的交互方式,应用程序进程持有了SystemServer进程中AMS/WMS等系统服务的远程代理Proxy,通过这个Proxy来调用SystemServer进程中的系统服务;SystemServer进程中也持有了应用程序进程中的ApplicationThread的远程代理Proxy,通过这个Proxy来调用应用程序进程中的方法。

       代码②处的app.thread就是ApplicationThread在SystemServer端的远程代理(Proxy),正式通过这个远程代理调用根Activity所在应用程序进程中的相关方法的从这里开始,流程就进入到目标应用程序进程了。

       由于该部分又繁琐,又没有涉及到直接创建和启动Activity的代码,所以这里就不贴代码了。对于这一部分的流程,个人建议读者没有必要太纠结细节,知道其大概做了些什么就够了。

5、在应用程序进程中创建和启动根Activity

       先看看ActivityThread类主要结构

【系统之音】Android系统启动篇-LMLPHP

       ActivityThread一般被称作主线程(当然它不是真正的线程),它包含两个很重要的内部类,ApplicationThread(前面已经介绍过了)和H。这个H是Handler的子类,拥有主线程的looper,所以其Callback的回调函数handleMessage运行在主现在当中,所以这个H类的作用其实就是将线程切换到主线程。

       我们结合上图来看看如下源码:

 1 //=======ActivityThread.java======
 2 private class ApplicationThread extends IApplicationThread.Stub {
 3       ......
 4       public final void scheduleLaunchActivity(...){
 5             ActivityClientRecord r = new ActivityClientRecord();
 6             ......
 7             r.intent = intent;
 8             ......
 9             sendMessage(H.LAUNCH_ACTIVITY, r);
10       }
11       ......
12 }
13
14 private void sendMessage(int what, Object obj) {
15     sendMessage(what, obj, 0, 0, false);
16 }
17
18 private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
19     ......
20     Message msg = Message.obtain();
21     msg.what = what;
22     msg.obj = obj;
23     msg.arg1 = arg1;
24     msg.arg2 = arg2;
25     ......
26     mH.sendMessage(msg);
27 }
28
29 final H mH = new H();
30 private class H extends Handler {
31     public static final int LAUNCH_ACTIVITY = 100;
32     public void handleMessage(Message msg) {
33         switch (msg.what) {
34                 case LAUNCH_ACTIVITY: {
35                       ......
36                       handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");//代码③
37                       ......
38                 }
39     }
40      ......
41 }

这样就明确了,此时的流程,又由ApplicationThread经过Handler进入到了主线程(ActivityThread)中了。

从代码③处开始,流程就由主线程ActivityThread来处理了,还是先上UML序列图:

【系统之音】Android系统启动篇-LMLPHP

【系统之音】Android系统启动篇-LMLPHP

 参照该图和如下源码,来看看应用程序进程是如何创建和启动Activity的:

 1 //=======ActivityThread.java=======
 2 private void handleLaunchActivity(...){
 3      ......
 4      WindowManagerGlobal.initialize();//代码④
 5      ......
 6      Activity a = performLaunchActivity(r, customIntent);//代码⑤
 7      if (a != null) {
 8          handleResumeActivity(...);//代码⑫
 9      }
10      ......
11 }

代码④,其作用是通过单例模式获取一个WMS在应用程序进程中的远程代理Proxy,我们知道,后面Activity中setContentView加载的layout文件,就需要通过WMS添加到Window中来显示。该方法代码比较简单:

 1 //========WindowManagerGlobal.java======
 2 ......
 3 private static IWindowManager sWindowManagerService;
 4 ......
 5 public static void initialize() {
 6     getWindowManagerService();
 7 }
 8 ......
 9 public static IWindowManager getWindowManagerService() {
10     synchronized (WindowManagerGlobal.class) {
11         if (sWindowManagerService == null) {
12             sWindowManagerService = IWindowManager.Stub.asInterface(
13                     ServiceManager.getService("window"));
14             ......
15         }
16         return sWindowManagerService;
17     }
18 }

进入到代码⑤处:

 1 //===========ActivityThread.java=======
 2 private Activity performLaunchActivity(...){
 3         ......
 4         Activity activity = null;
 5         try {
 6             java.lang.ClassLoader cl = appContext.getClassLoader();
 7             activity = mInstrumentation.newActivity(
 8                     cl, component.getClassName(), r.intent);//代码⑥
 9             ......
10         } catch (Exception e) {
11             ......
12         }
13         try {
14             Application app = r.packageInfo.makeApplication(false, mInstrumentation);//代码⑦
15               ......
16               activity.attach(...);
17               ......
18              if (r.isPersistable()) {
19                     mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); //代码⑩-1
20                 } else {
21                     mInstrumentation.callActivityOnCreate(activity, r.state);//代码⑩-2
22                 }
23               ......
24                 if (!r.activity.mFinished) {
25                     activity.performStart();//代码⑪
26                     ......
27                 }
28               ......
29              } catch (Exception e) {
30             ......
31         }
32         ......
33 }

代码⑥处,以ClassLoader的方式创建Activity实例:

 1 //================Instrumentation.java=====
 2 /**
 3  * Perform instantiation of the process's {@link Activity} object.
 4  * ......
 5  * @return The newly instantiated Activity object.
 6  */
 7 public Activity newActivity(ClassLoader cl, String className,
 8         Intent intent)
 9         throws InstantiationException, IllegalAccessException,
10         ClassNotFoundException {
11     return (Activity)cl.loadClass(className).newInstance();
12 }

从代码⑦处深入,该代码的作用在于处理Application相关的业务:

 1 //=========LoadedApk.java=========
 2 public Application makeApplication(...){
 3     if (mApplication != null) {
 4             return mApplication;
 5         }
 6      ......
 7      Application app = null;
 8      ......
 9         try {
10             java.lang.ClassLoader cl = getClassLoader();
11             ......
12             app = mActivityThread.mInstrumentation.newApplication(
13                     cl, appClass, appContext); //代码⑧
14             ......
15         } catch (Exception e) {
16            ......
17         }
18         mActivityThread.mAllApplications.add(app);
19         mApplication = app;
20         if (instrumentation != null) {
21             try {
22                 instrumentation.callApplicationOnCreate(app);//代码⑨
23             } catch (Exception e) {
24                 ......
25             }
26         }
27         ......
28 }

代码⑧处,也是以ClassLoader方式创建Application实例:

 1 //================Instrumentaion.java=========
 2 /**
 3  * Perform instantiation of the process's {@link Application} object.
 4  * ......
 5  * @return The newly instantiated Application object.
 6  */
 7 public Application newApplication(ClassLoader cl, String className, Context context)
 8         throws InstantiationException, IllegalAccessException,
 9         ClassNotFoundException {
10     return newApplication(cl.loadClass(className), context);
11 }
12
13 /**
14  * Perform instantiation of the process's {@link Application} object.
15  * ......
16  * @return The newly instantiated Application object.
17  */
18 static public Application newApplication(Class<?> clazz, Context context)
19         throws InstantiationException, IllegalAccessException,
20         ClassNotFoundException {
21     Application app = (Application)clazz.newInstance();
22     app.attach(context);
23     return app;
24 }

代码⑨处,调用Application的onCreate方法,在自定义的Application中,重写的onCreate方法开始执行:

 1 //=============LoadedApk.java========
 2 /**
 3  * Perform calling of the application's {@link Application#onCreate} method.
 4  * ......
 5  * @param app The application being created.
 6  */
 7 public void callApplicationOnCreate(Application app) {
 8     app.onCreate();
 9 }
10
11 //=========Application.java========
12 @CallSuper
13 public void onCreate() {
14 }

代码⑩(代码⑩-1或代码⑩-2)中,执行Activity的onCreate方法,根Activity中的onCreate方法执行:

 1 //==============Instrumentation.java========
 2 /**
 3  * Perform calling of an activity's {@link Activity#onCreate} method.
 4  * ......
 5  */
 6 public void callActivityOnCreate(Activity activity, Bundle icicle) {
 7     prePerformCreate(activity);
 8     activity.performCreate(icicle);
 9     postPerformCreate(activity);
10 }
11 /**
12  * Perform calling of an activity's {@link Activity#onCreate} method.
13  * ......
14  */
15 public void callActivityOnCreate(Activity activity, Bundle icicle,
16         PersistableBundle persistentState) {
17     prePerformCreate(activity);
18     activity.performCreate(icicle, persistentState);
19     postPerformCreate(activity);
20 }
21
22 //==========Activity.java========
23 final void performCreate(Bundle icicle) {
24     performCreate(icicle, null);
25 }
26 final void performCreate(Bundle icicle, PersistableBundle p
27     ......
28     if (persistentState != null) {
29         onCreate(icicle, persistentState);
30     } else {
31         onCreate(icicle);
32     }
33     ......
34 }
35
36 public void onCreate(@Nullable Bundle savedInstanceState,
37         @Nullable PersistableBundle persistentState) {
38     onCreate(savedInstanceState);
39 }
40
41 @MainThread
42 @CallSuper
43 protected void onCreate(@Nullable Bundle savedInstanceState) {
44     ......
45 }
代码⑪开始执行Activity的onStart方法,根Activity的onStart方法开始执行:
 1 //======Activity.java======
 2 final void performStart() {
 3     ......
 4     mInstrumentation.callActivityOnStart(this);
 5     ......
 6 }
 7
 8 //=========Instrumentation.java=========
 9 /**
10  * Perform calling of an activity's {@link Activity#onStart} method.
11  * ......
12  */
13 public void callActivityOnStart(Activity activity) {
14     activity.onStart();
15 }
16
17 //======Activity.java======
18 @CallSuper
19 protected void onStart() {
20     ......
21 }
代码⑫的handleResumeActivity方法用于处理resume相关的业务:
 1 //========ActivityThread.java======
 2 final void handleResumeActivity(...){
 3       ......
 4       r = performResumeActivity(token, clearHide, reason);//代码⑬
 5       ......
 6       //如下过程将DecorView添加到窗口中 代码段⑯
 7       r.window = r.activity.getWindow(); //PhoneWindow实例
 8       View decor = r.window.getDecorView(); //DecorView实例
 9       decor.setVisibility(View.INVISIBLE);
10       ViewManager wm = a.getWindowManager();
11       WindowManager.LayoutParams l = r.window.getAttributes();
12       a.mDecor = decor;
13       ......
14       ViewRootImpl impl = decor.getViewRootImpl();
15       ......
16       wm.addView(decor, l);
17       ......
18 }

深入代码⑬中:

 1 //======ActivityThread=======
 2 public final ActivityClientRecord performResumeActivity(...){
 3       ......
 4       r.activity.performResume();
 5       ......
 6 }
 7
 8 //======Activity.java=====
 9 final void performResume() {
10      performRestart();//代码⑭
11      ......
12      mInstrumentation.callActivityOnResume(this);//代码⑮
13      ......
14 }

代码⑭用于处理reStart相关的业务,当前场景是新创建根Activity,所以不会走这个流程;如果是从其它界面回退到这个activity,就会走调用onRestart和onStart的流程:

 1 //===========Activity.java========
 2 final void performRestart() {
 3      ......
 4      if (mStopped) {
 5           mStopped = false;
 6           ......
 7           mInstrumentation.callActivityOnRestart(this);
 8           ......
 9           performStart();
10      }
11 }
12
13 //============Instrumentation.java===========
14 /**
15  * Perform calling of an activity's {@link Activity#onRestart} method.
16  * ......
17  * @param activity The activity being restarted.
18  */
19 public void callActivityOnRestart(Activity activity) {
20     activity.onRestart();
21 }
22
23 //===========Activity.java===========
24 @CallSuper
25 protected void onRestart() {
26     mCalled = true;
27 }
28
29 final void performStart() {
30      ......
31      mInstrumentation.callActivityOnStart(this);
32      ......
33 }
34
35 //============Instrumentation.java==========
36 /**
37  * Perform calling of an activity's {@link Activity#onStart} method.
38  *  ......
39  * @param activity The activity being started.
40  */
41 public void callActivityOnStart(Activity activity) {
42     activity.onStart();
43 }
44 //==============Activity.java============
45 @CallSuper
46 protected void onStart() {
47    ......
48 }

代码⑮处调用acitvity的onResume方法,这样一来根Activity的onResume回调方法就执行了:

 1 //========Instrumentation.java=========
 2 /**
 3  * Perform calling of an activity's {@link Activity#onResume} method.
 4  *  ......
 5  * @param activity The activity being resumed.
 6  */
 7 public void callActivityOnResume(Activity activity) {
 8     ......
 9     activity.onResume();
10     ......
11 }
12
13 @CallSuper
14 protected void onResume() {
15     ......
16 }

代码段⑯(对应第7~16行)的作用在于将DecorView添加到Window,并完成界面的绘制流程。我们知道,根Activity在onCreate生命周期回调方法中会通过setContentView方法加载layout布局文件,将其加入到DecorView中,绘制部分详情可以阅读【【朝花夕拾】Android自定义View篇之(一)View绘制流程】。

       这样,应用程序进程就完成了根Activity的创建和启动,界面也完成了显示。从上面的UML图和源码分析,可以发现这部分笔者是按照Activity的生命周期为主线来介绍的,实际上读者完全可以结合Activity的生命周期来理解和记忆这部分的主要流程。下图再次总结了这部分的主要流程:

 【系统之音】Android系统启动篇-LMLPHP

       想必读者应该对第4~7步的生命周期顺序非常熟悉了。需要注意的是,第2和第3步可能会和我们平时的认知有些出入,实际上Activity的实例比Application的实例要更早创建。第1和第8步是关于图形界面显示的,也需要重点关心。

6、其它Activity启动场景流程

       到目前为止,从Laucher中点击一个快捷图标来启动根Activity的整个流程就介绍完毕了,这个场景搞清楚了,其它场景就不在话下了。比如,从Launcher中启动一个应用程序进程已经启动的应用的根Activity,就在上述流程基础上少了Zytote创建应用程序进程这一步,如下图:

【系统之音】Android系统启动篇-LMLPHP

 比如,应用程序内部启动另外一个新Activity时,就只需要考虑应用程序进程和SystemSever两个进程,如下图:

【系统之音】Android系统启动篇-LMLPHP

还有从其它应用中启动指定某另外应用中的Activity的场景和从Launcher启动的流程类似;再次打开一个已经启动的Activity,就无需走create流程,而是走onRestart-onStart-onResume生命周期流程,等等,这里就不一一列举了。 

       本文已经尽可能地包含了完整的流程,但同时力求简洁易懂,摒弃大量具体细节,只抽取关键流程。尽管如此,但是这部分内容确实比较复杂,还是花了这么长的篇幅,感谢读者的耐心阅读。由于笔者水平有限,有些描述不准确或者不妥之处,请读者朋友不吝赐教,感谢!

参考资料

     【朝花夕拾】Android自定义View篇之(一)View绘制流程

     【系统之音】Android系统启动篇

     Activity启动流程详解

     刘望舒《Android进阶解密》

08-15 15:07