Activity启动流程(笔记)

由于Activity的启动涉及到的知识太多,本文不会展开太多,主要以记录启动流程为主。
Activity启动流程,我们肯定是从Activity#startActivity()着手(本文源码为26版本)。

1)Activity#startActivity()

    Activity.startActivity()
        =>Activity.startActivityForResult()
        =>Instrumentation.execStartActivity();

2)Instrumentation#execStartActivity()

    Instrumentation.execStartActivity()
        =>ActivityManager.getService().startActivity()
  2.1)ActivityManager.getService()
  public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

  这里从ActivityManager中的IActivityManagerSingleton单例中获取到一个IActivityManager,IActivityManager是ServiceManager.getService(Context.ACTIVITY_SERVICE)获取到的一个远程服务通过Binder对应的代理,而这个远程服务就是ActivityManagerService(AMS),所以ActivityManager.getService().startActivity()实际是调用ActivityManagerService.startActivity()。

3)ActivityManagerService#startActivity()

Tips:从这里开始就已经是运行在ActivityManagerService进程了。

    ActivityManagerService.startActivity()
        =>ActivityManagerService.startActivityAsUser()
        =>ActivityStarter.startActivityMayWait()

ActivityStarter是Activity的启动器,用来启动Activity,它是在ActivityManagerService的构造方法中创建,ActivityManagerService的创建之后会在《ActivityManagerService的启动流程》中说明。

4)ActivityStarter#startActivityMayWait()

    ActivityStarter.startActivityMayWait()
        =>ActivityStarter.startActivityLocked()
        =>ActivityStarter.startActivity()
        =>ActivityStarter.startActivity()(重载)
        =>ActivityStarter.startActivityUnchecked()
        =>ActivityStackSupervisor.resumeFocusedStackTopActivityLocked()

ActivityStackSupervisor是Activity栈的管理员,用来管理Activity栈,它是在ActivityManagerService的构造方法中创建,ActivityManagerService的创建之后会在《ActivityManagerService的启动流程》中说明。

5)ActivityStackSupervisor#resumeFocusedStackTopActivityLocked()

    ActivityStackSupervisor.resumeFocusedStackTopActivityLocked()
        =>ActivityStack.resumeTopActivityUncheckedLocked()
        =>ActivityStack.resumeTopActivityInnerLocked()
        =>ActivityStackSupervisor.startSpecificActivityLocked()
    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // 获取启动的Activity对应的进程
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.getStack().setLaunchTime(r);
        //如果进程已经存在
        if (app != null && app.thread != null) {
                //启动Activity
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
        }
         //如果进程不存在,开启新进程
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

这里暂时只看进程存在的情况,新开进程会在之后新开一篇笔记来记录。

    =>ActivityStackSupervisor.realStartActivityLocked()
    =>ProcessRecord.thread.scheduleLaunchActivity()

Tips:很明显我们在App启动一个Activity,这个Activity是需要运行在当前App进程的,而从step3开始启动流程就已经切到了AMS所在进程,所以最终还是需要AMS通知App进程来创建Activity,这里的ProcessRecord.thread就是一个Binder接口,它实际上就是在step3中传入的ActivityThread.mAppThread,这样AMS便持有了一个可以与ActivityThread通信的Binder对应代理。

6)ApplicationThread#scheduleLaunchActivity()

Tips:这里已经回到App进程。

    ApplicationThread.scheduleLaunchActivity()
        =>ActivityThread.sendMessage(H.LAUNCH_ACTIVITY, r)
    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

可以看到这里就是往mH(ActivityThread中的Handler)中发送了一个what=H.LAUNCH_ACTIVITY的Message。
我们找到这个消息接收的地方:

        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
        }
         =>ActivityThread.handleLaunchActivity()

7)ActivityThread#handleLaunchActivity()

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        //7.1
        Activity a = performLaunchActivity(r, customIntent);
        if (a != null) {
            //7.2
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
            if (!r.activity.mFinished && r.startsNotResumed) {
                performPauseActivityIfNeeded(r, reason);//6.3
            }
        } 
    }
  7.1)ActivityThread. performLaunchActivity()
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        //7.1.1
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        //7.1.2
        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);

        //7.1.3
        if (r.isPersistable()) {
             mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        } else {
             mInstrumentation.callActivityOnCreate(activity, r.state);
        }

         //7.1.4
        if (!r.activity.mFinished) {
            activity.performStart();
            r.stopped = false;
        }
    }
    7.1.1)Instrumentation.newActivity()创建Activity

    通过以上代码可以看到Activity是通过Instrumentation.newActivity()返回

    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }

    Tips:这里可以看出Activity实际是Instrumentation反射生成的。

    7.1.2)创建Activity后,将AppContext、当前ActivityThread、Instrumentation、以及一些Activity相关信息传入。
    7.1.3)Instrumentation.callActivityOnCreate()执行Activity.onCreate()
    public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
    }

    Activity.performCreate()

    final void performCreate(Bundle icicle) {
        restoreHasCurrentPermissionRequest(icicle);
        //**
        onCreate(icicle);
        //**
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

    可以看到到这里Activity的onCreate()就被显示的调用了

    7.1.4)Activity.performStart()
    Activity.performStart()
        =>Instrumentation.callActivityOnStart()
        =>Activity.onStart()

    Activity调用onCreate()后马上调用了onStart().

  7.2)ActivityThread. handleResumeActivity()
    final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        //7.2.1
        r = performResumeActivity(token, clearHide, reason);

         //7.2.2
        if (r != null) {
            final Activity a = r.activity;

            if (localLOGV) Slog.v(
                TAG, "Resume " + r + " started activity: " +
                a.mStartedActivity + ", hideForNow: " + r.hideForNow
                + ", finished: " + a.mFinished);

            final int forwardBit = isForward ?
                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

            // If the window hasn't yet been added to the window manager,
            // and this guy didn't finish itself or start another activity,
            // then go ahead and add the window.
            boolean willBeVisible = !a.mStartedActivity;
            if (!willBeVisible) {
                try {
                    willBeVisible = ActivityManager.getService().willActivityBeVisible(
                            a.getActivityToken());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (r.mPreserveWindow) {
                    a.mWindowAdded = true;
                    r.mPreserveWindow = false;
                    // Normally the ViewRoot sets up callbacks with the Activity
                    // in addView->ViewRootImpl#setView. If we are instead reusing
                    // the decor view we have to notify the view root that the
                    // callbacks may have changed.
                    ViewRootImpl impl = decor.getViewRootImpl();
                    if (impl != null) {
                        impl.notifyChildRebuilt();
                    }
                }
                if (a.mVisibleFromClient) {
                    if (!a.mWindowAdded) {
                        a.mWindowAdded = true;
                        wm.addView(decor, l);
                    } else {
                        // The activity will get a callback for this {@link LayoutParams} change
                        // earlier. However, at that time the decor will not be set (this is set
                        // in this method), so no action will be taken. This call ensures the
                        // callback occurs with the decor set.
                        a.onWindowAttributesChanged(l);
                    }
                }

            // If the window has already been added, but during resume
            // we started another activity, then don't yet make the
            // window visible.
            } else if (!willBeVisible) {
                if (localLOGV) Slog.v(
                    TAG, "Launch " + r + " mStartedActivity set");
                r.hideForNow = true;
            }

            // Get rid of anything left hanging around.
            cleanUpPendingRemoveWindows(r, false /* force */);

            // The window is now visible if it has been added, we are not
            // simply finishing, and we are not starting another activity.
            if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
                if (r.newConfig != null) {
                    performConfigurationChangedForActivity(r, r.newConfig);
                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
                            + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig);
                    r.newConfig = null;
                }
                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
                        + isForward);
                WindowManager.LayoutParams l = r.window.getAttributes();
                if ((l.softInputMode
                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
                        != forwardBit) {
                    l.softInputMode = (l.softInputMode
                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
                            | forwardBit;
                    if (r.activity.mVisibleFromClient) {
                        ViewManager wm = a.getWindowManager();
                        View decor = r.window.getDecorView();
                        wm.updateViewLayout(decor, l);
                    }
                }

                r.activity.mVisibleFromServer = true;
                mNumVisibleActivities++;
                if (r.activity.mVisibleFromClient) {
                    r.activity.makeVisible();
                }
            }

            if (!r.onlyLocalRequest) {
                r.nextIdle = mNewActivities;
                mNewActivities = r;
                if (localLOGV) Slog.v(
                    TAG, "Scheduling idle handler for " + r);
                Looper.myQueue().addIdleHandler(new Idler());
            }
            r.onlyLocalRequest = false;

            // Tell the activity manager we have resumed.
            if (reallyResume) {
                try {
                    ActivityManager.getService().activityResumed(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }

        }
    }
    7.2.1)ActivityThread.performResumeActivity()
    ActivityThread.performResumeActivity()
        =>Activity.performResume()
        =>Instrumentation.callActivityOnResume()
        =>Activity.onResume()

    这里完成了Activity.onResume()的显示调用

    7.2.2)到这里才真正的开始绘制页面,将页面布局添加到window的DecorView。

总结:

Activity在用户进程启动时,通过Binder机制获取到AMS的代理,然后调用AMS的startActivity(),AMS中ActivityStarter、ActivityStackSupervisor、ActivityStack共同完成启动activity的系统工作,之后通过传入的ApplicationThread代理通知到ActivityThread,回到用户进程,通过Instrumentation完成Activity的创建,以及各个启动声明周期的回调。

这里有2个细节可以留意一下:
1.Activity是在Instrumentation中反射生成的;
2.Activity是在回调完onResume()后才开始绘制页面的。

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