一、App(Activity)启动流程

理论知识

1. 涉及进程

1.1 zygote

在Android系统里面,zygote是一个进程的名字。Android是基于Linux系统的,当手机开机的时候,Linux的内核加载完成之后就会启动一个叫“init“的进程。在Linux 系统里面,所有的进程都是由init进程fork出来的,我们的zygote进程也不例外。
为了实现资源共用和更快的启动速度,Android系统开启新进程的方式是:fork zygote进程实现的。所以,其他应用所在的进程都是zygote进程的子进程

1.2 SystemServer

也是一个进程,是由zygote进程fork出来的。是Android Framework里面两大非常重要的进程之一(SystemServer和zygote进程)。系统里面重要的服务都是在这个进程里面开启的,比如:
ActivityManagerService、PackageManagerService、WindowManagerService等等。

在zygote开启的时候,会调用ZygoteInit.main()进行初始化。

public static void main(String argv[]) {

     ...

    //在加载首个zygote的时候,会传入初始化参数,使得startSystemServer = true
     boolean startSystemServer = false;
     for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            ...

         //开始fork我们的SystemServer进程
     if (startSystemServer) {
                startSystemServer(abiList, socketName);
         }

     ...
}

    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {

         ...
        int pid;
        try {
            ...
            /* Request to fork the system server process,这里 fork出systemServer */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

那上面提到的ActivityManagerService、PackageManagerService、WindowManagerService等重要服务,是什么时候在SystemServer进程开启的?

public final class SystemServer {

    //zygote的主入口
    public static void main(String[] args) {
        new SystemServer().run();
    }

    private void run() {

        ...
        //开启服务
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }
        ...
    }

    ...
}

显然,在SystemServer进程开启的时候,就会初始化ActivityManagerService等重要服务。

1.3 Launcher

其实每一个App其实都是:1. 一个单独的dalvik虚拟机 2. 一个单独的进程
Launcher本质上也是一个App,也是继承自Activity。我们点击手机桌面上的图标就是Launcher相应不同的点击事件,startActivity不同的Activity而已。所以它也占一个进程。

1.4 应用进程

就是你要打开的App所在的进程,在桌面点击应用图标打开应用时,如果应用进程不存在会先创建。是应用的主线程(新创建的进程就是主线程),处理组件生命周期、界面绘制等相关事情。


2. 涉及对象概念

  • Instrumentation: 每个Activity都持有Instrumentation对象的一个引用,但是整个进程只会存在一个Instrumentation对象。是完成对Application和Activity初始化和生命周期调用的工具类。

  • ActivityManagerService(AMS):服务端对象,负责系统中所有Activity的生命周期。

  • ActivityStarter:Activity启动的控制器,处理Intent与Flag对Activity启动的影响,主要功能是:1. 寻找符合启动条件的Activity,如果有多个,让用户选择;2. 校验启动参数的合法性; 3. 返回int参数,代表Activity是否启动成功。

  • ActivityStack:用来管理任务栈里的Activity。
  • ActivityRecord:ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。
  • ActivityStackSupervisior:这是高版本才有的类,它用来管理多个ActivityStack。早期的版本只有一个ActivityStack对应着手机屏幕,后来高版本支持多屏以后,就有了多个ActivityStack,于是就引入了ActivityStackSupervisior用来管理多个ActivityStack。
  • ActivityThread:App的真正入口。当开启App之后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作
  • ApplicationThread:ActivityThread的内部类,用来实现AMS与ActivityThread之间的交互。在ActivityManagerService需要管理相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯。

Activity的启动流程源码分析请看:Activity启动流程(基于Android26)

Activity的启动流程时序图(对着上面的概念去理解时序图):

启动流程时序图

我们可以来分析 handleLaunchActivity 之后的内容:

private void handleLaunchActivity() {
    ...
    // 执行启动 Activity
    Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
        ...
        // resume activity
        handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
    } else {
        ...
    }
}

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // 1. 从ActivityClientRecord 中获取待启动的Activity的组件信息
        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }
        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }
        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

        // 2. 通过Instrumentation的newActivity方法使用类加载器创建Activity对象
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            ...
        } catch (Exception e) {
           ...
        }        


        try {
            // 3. makeApplication尝试创建Application
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

      

            if (activity != null) {
                ...
                // 4. 通过Activity的attach方法来完成一些重要数据的初始化
                appContext.setOuterContext(activity);
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);

                ...
                // 5. 通过Instrumentation调用Activity的onCreate方法,这意味着Activity已经完成了整个启动过程
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;

                // 6. Activity onStart
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                // 7. 通过 Instrumentation 执行 Activity onRestoreInstanceState
                if (!r.activity.mFinished) {
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                // 8. 通过 Instrumentation 执行 Activity onPostCreate
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }
                    ...
                }
            }
            r.paused = true;
            mActivities.put(r.token, r);

        } catch () {
           ...
        } 

        return activity;
    }
-> Activity.java
    final void performCreate(Bundle icicle) {
        ...
        onCreate(icicle);
        ...
    }

    final void performStart() {
        ...
        mInstrumentation.callActivityOnStart(this);
        ...
    }
  • Activity的attach中,还会完成Window的创建并建立自己和Window的关联,这样当Window接收到外部输入事件后就可以将事件传递给Activity
    关于Activity的Window的创建过程,可以参考:二、Activity的Window创建过程与关联View
  • 想获取某个view的宽高信息,必须在view绘制完成后。如果在onCreate方法里面getWidth(),getHight()得到都为0,这个时候可以利用onPostCreate方法。它是onCreate方法彻底执行完毕的回调。现在知道的做法也就只有在使用ActionBarDrawerToggle的使用在onPostCreate需要在屏幕旋转时候等同步下状态,Google官方提供的实例如下:
@Overrideprotected void onPostCreate(Bundle savedInstanceState) {    
        super.onPostCreate(savedInstanceState);     
        // Sync the toggle state after onRestoreInstanceState has occurred.    
        mDrawerToggle.syncState();
}

总体上来说就是在performLaunchActivity方法里面完成了Activity的创建、初始化等。
接下来就会在handleLaunchActivity方法里面调用handleResumeActivity。

整个流程可以概括如下:


image.png

总结

App与AMS通过Binder进行IPC通信,AMS(SystemServer进程)与zygote通过Socket进行IPC通信。
AMS负责系统中所有Activity的生命周期,因为所有的Activity的开启、暂停、关闭都需要AMS来控制。


参考:
Activity启动过程全解析
一个APP从启动到主页面显示经历了哪些过程?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,039评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,426评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,417评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,868评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,892评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,692评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,416评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,326评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,782评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,957评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,102评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,790评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,442评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,996评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,113评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,332评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,044评论 2 355

推荐阅读更多精彩内容