【Android 13源码分析】Activity生命周期之onCreate,onStart,onResume-2

忽然有一天,我想要做一件事:去代码中去验证那些曾经被"灌输"的理论。

-- 服装学院的IT男

由于篇幅原因,分为以下2篇:

Activity生命周期之onCreate,onStart,onResume-1

Activity生命周期之onCreate,onStart,onResume-2

本篇为第二篇,介绍应用端 onCreate,onStart,onResume 的处理

1. onCreate

onCreate 是一个新 Activity 启动的第一个生命周期。而且根据前面的铺垫,也知道了他是在 onStart 和 onResume 执行的。 对应的事务为 LaunchActivityItem

typescript 复制代码
# LaunchActivityItem
    @Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
            // trace
            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
            ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                    mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                    mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
                    client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
                    mTaskFragmentToken);
            // 应用段处理
            client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
    @Override
    public void postExecute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        
            client.countLaunchingActivities(-1);
    }

完整的调用链如下:

arduino 复制代码
LaunchActivityItem::execute
    ActivityThread::handleLaunchActivity
        ActivityThread::performLaunchActivity
            Instrumentation::newActivity      --- 创建Activity
            Activity::attach                  --- 创建Window
                Window::init
                Window::setWindowManager
            Instrumentation::callActivityOnCreate  
                Activity::performCreate
                    Activity::onCreate        --- onCreate
            ActivityClientRecord::setState    --- 设置状态为 ON_CREATE(1)

这部分的代码其实在【Activity启动流程-3】的末尾有解释,单独拎出来再看一遍。

scss 复制代码
# ActivityThread

    public Activity handleLaunchActivity(ActivityClientRecord r,
                PendingTransactionActions pendingActions, Intent customIntent) {
                    ......
                    final Activity a = performLaunchActivity(r, customIntent);
                    ......
                }
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ......
                Activity activity = null;
                try {
                    // 重点* 1. 通过Instrumentation 反射创建Activity
                    java.lang.ClassLoader cl = appContext.getClassLoader();
                    activity = mInstrumentation.newActivity(
                            cl, component.getClassName(), r.intent);
                    ......
                }
                try {
                    ......
                    // 重点* 2. 执行 attach 流程
                    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.activityConfigCallback,
                            r.assistToken, r.shareableActivityToken);
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                    } else {
                        重点* 3. OnCreate流程
                        mInstrumentation.callActivityOnCreate(activity, r.state);
                    }
                    // 设置状态为 ON_CREATE(1)
                    r.setState(ON_CREATE);
                } ......
        ......
    }

# Instrumentation
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        // onCreate流程
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }
# Activity
    final void performCreate(Bundle icicle) {
        performCreate(icicle, null);
    }
    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        ......
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            // 执行onCreate
            onCreate(icicle);
        }
        // wm_on_create_called
        EventLogTags.writeWmOnCreateCalled(mIdent, getComponentName().getClassName(),
                "performCreate");
        ......
    }

onCreate 的流程还是比较简单的,在 ActivityThread::performLaunchActivity 做了四件事:

    1. 反射创建 Activity 对象
    1. 执行 activity.attach,这里会创建Window
    1. 执行到 onCreate 生命周期
    1. 设置 ActivityClientRecord 中的状态为 ON_CREATE(1)

这里需要留意下会先执行 Activity::attach 来创建Window,然后才是后面的 Activity的onCreate。 创建 Window 的时候会创建 DecorView,有了这个 DecorView 我们在 onCreate 的时候才可以把对应的XML布局设置进去。

2. onStart

onStart 也有其对应的一个事务: StartActivityItem ,我一度以为启动 Activity 的时候也是通过这个事务来触发 onStart 的,但是实际情况我有点意外,它不是通过事务触发的,而是在执行 ResumeActivityItem 前,通过 TransactionExecutor::cycleToPath 触发的。

按下 recent 键再回到 Activity,这个时候onStart 是通过 StartActivityItem 触发的

当前分析 TransactionExecutor::cycleToPath 方法

java 复制代码
# TransactionExecutor
    // 工具类
    private TransactionExecutorHelper mHelper = new TransactionExecutorHelper();    

    private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
            ClientTransaction transaction) {
        // 1. 获取当前ActivityClientRecord的生命周期状态值
        final int start = r.getLifecycleState();
        // log 
        if (DEBUG_RESOLVER) {
            Slog.d(TAG, tId(transaction) + "Cycle activity: "
                    + getShortActivityName(r.token, mTransactionHandler)
                    + " from: " + getStateName(start) + " to: " + getStateName(finish)
                    + " excludeLastState: " + excludeLastState);
        }
        // 2. 根据起始状态、结束状态以及是否排除最后一个状态,计算出生命周期状态变化的路径
        final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
        // 3. 按照计算出的生命周期状态路径顺序执行相关操作
        performLifecycleSequence(r, path, transaction);
    }
    1. 获取到当前 Activity 的生命周期状态,目前是 ON_CREATE 也就是 1
    1. 通过工具类 计算出生命周期变化的路径,这个路径是啥呢, 比如说当前是 ON_CREATE(1),需要到 ON_RESUME(3), 那路径就是 [2]
    1. 根据第二步计算的路径开始执行各个生命周期

2.1 getLifecyclePath 计算生命周期切换路径

TransactionExecutor::getLifecyclePath 方法完整代码和解释都在下面了,但是我个人建议了解一下即可,大概浏览一下,留意我代码加了1,2,3 这3个重点的地方即可。

csharp 复制代码
# TransactionExecutorHelper
    // 定义需要经过的生命周期路径,长度为6(毕竟一共也才7个生命周期)
    @ActivityLifecycleItem.LifecycleState
    private IntArray mLifecycleSequence = new IntArray(6);

    // start   :开始的生命周期状态
    // finish  :结束的生命周期状态
    // excludeLastState :是否移除最后一个状态
    public IntArray getLifecyclePath(int start, int finish, boolean excludeLastState) {

        // 如果开始状态或结束状态未定义,则抛出异常
        if (start == UNDEFINED || finish == UNDEFINED) {
            throw new IllegalArgumentException("Can't resolve lifecycle path for undefined state");
        }

        // 如果开始状态或结束状态是ON_RESTART,则抛出异常,因为在生命周期中不能以此状态开始或结束
        if (start == ON_RESTART || finish == ON_RESTART) {
            throw new IllegalArgumentException(
                    "Can't start or finish in intermittent RESTART state");
        }

        // 如果结束状态为PRE_ON_CREATE且开始状态不等于结束状态,则抛出异常,只能从预创建状态开始
        if (finish == PRE_ON_CREATE && start != finish) {
            throw new IllegalArgumentException("Can only start in pre-onCreate state");
        }

        // 重点* 1. 清空用于存储生命周期状态变更序列的集合
        mLifecycleSequence.clear();

        // 重点* 2. 分情况计算生命周期状态变更路径 (正常场景)
        if (finish >= start) {
            // 如果结束状态大于等于开始状态
            if (start == ON_START && finish == ON_STOP) {
                // 特殊情况:从开始到停止状态,无需经过暂停和恢复状态
                mLifecycleSequence.add(ON_STOP);
            } else {
                // 重点* 3. 普通情况:直接将中间的所有状态加入序列 (正常场景)
                for (int i = start + 1; i <= finish; i++) {
                    mLifecycleSequence.add(i);
                }
            }
        } else { // 结束状态小于开始状态,不能简单地向下循环
            if (start == ON_PAUSE && finish == ON_RESUME) {
                // 特殊情况:从暂停直接到恢复状态
                mLifecycleSequence.add(ON_RESUME);
            } else if (start <= ON_STOP && finish >= ON_START) {
                // 开始状态在ON_STOP之前且结束状态在ON_START之后的情况
                // 先转为停止状态
                for (int i = start + 1; i <= ON_STOP; i++) {
                    // 添加
                    mLifecycleSequence.add(i);
                }
                // 添加
                mLifecycleSequence.add(ON_RESTART);
                // 再转到指定结束状态
                for (int i = ON_START; i <= finish; i++) {
                    mLifecycleSequence.add(i);
                }
            } else {
                // 其他情况:需要重新启动并转到指定状态
                // 先转到销毁状态
                for (int i = start + 1; i <= ON_DESTROY; i++) {
                    // 添加
                    mLifecycleSequence.add(i);
                }
                // 再转到指定结束状态
                for (int i = ON_CREATE; i <= finish; i++) {
                    // 添加
                    mLifecycleSequence.add(i);
                }
            }
        }

        // 如果要求排除最后一个状态并且生命周期序列不为空,则移除最后一个状态
        if (excludeLastState && mLifecycleSequence.size() != 0) {
            mLifecycleSequence.remove(mLifecycleSequence.size() - 1);
        }

        // 返回计算好的生命周期状态变更序列
        return mLifecycleSequence;
    }

根据当前分析的场景,这个方法执行一下3步:

    1. 清除集合的数据,避免有脏数据影响结果
    1. 当前第一个参数是 ON_CREATE(1), 第二个参数定义在 ResumeActivityItem 下,返回值是 ON_RESUME(3),满足finish >= start的条件,所以进if语句
    1. 走 else 逻辑,最终 mLifecycleSequence 下也就一个元素 : 2 ,返回返回

2.2 performLifecycleSequence 切换Activity的生命周期

上一小节计算出需要执行的生命周期路径后,现在就要开始应用了。

arduino 复制代码
# TransactionExecutor
    // 实际执行在 ActiviThread
    private ClientTransactionHandler mTransactionHandler;
    // 构造方法赋值
    public TransactionExecutor(ClientTransactionHandler clientTransactionHandler) {
        mTransactionHandler = clientTransactionHandler;
    }

    private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
            ClientTransaction transaction) {
            // 当前场景就1个元素
            final int size = path.size();
            // 开始遍历
            for (int i = 0, state; i < size; i++) {
                // 获取到状态,当前就1个元素:ON_START( 2)
                state = path.get(i);
                // 打印log
                if (DEBUG_RESOLVER) {
                    Slog.d(TAG, tId(transaction) + "Transitioning activity: "
                            + getShortActivityName(r.token, mTransactionHandler)
                            + " to state: " + getStateName(state));
                }
                switch (state) {
                    ......
                    case ON_START:
                        mTransactionHandler.handleStartActivity(r, mPendingActions,
                                null /* activityOptions */);
                        break;
                    ......
                }         
            }
        }

mTransactionHandler 在构造 TransactionExecutor 的构造方法赋值,创建对象的地方在 ActivityThread 中,传递的参数是 this,而 ActivityThread 是 ClientTransactionHandler 的子类,也就是说 mTransactionHandler 真正的实现还是在 ActivityThread。

java 复制代码
# ActivityThread
    @Override
    public void handleStartActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, ActivityOptions activityOptions) {
            // 拿到 Activity
            final Activity activity = r.activity;
            ......
            // Start
            // 重点* 1. 执行onStart
            activity.performStart("handleStartActivity");
            // 2. 更新对应的状态
            r.setState(ON_START);
            ......
            // 重点* 3. 更新可见性,参数为true
            updateVisibility(r, true /* show */);
            mSomeActivitiesChanged = true;
            ......
        }

一共处理了3件事,其中设置状态的逻辑之前看过了,看看另外2个重点流程。

2.3 onStart 流程

scss 复制代码
# Activity
    final void performStart(String reason) {
        ......
        // 执行onStart
        mInstrumentation.callActivityOnStart(this);
        // wm_on_start_called
        EventLogTags.writeWmOnStartCalled(mIdent, getComponentName().getClassName(), reason);
        ......
        // Fragment 处理
        mFragments.dispatchStart();
        ......
    }

# Instrumentation

    public void callActivityOnStart(Activity activity) {
        activity.onStart();
    }

到这里 Activity 的 onStart 就执行了。

2.4 设置 View 可见

上一小节先执行到 onStart ,然后会设置 View 的可见性, 看一下具体代码

ini 复制代码
# ActivityThread
    private void updateVisibility(ActivityClientRecord r, boolean show) {
        // 拿到DecorView
        View v = r.activity.mDecor;
        if (v != null) {
            if (show) {
                if (!r.activity.mVisibleFromServer) {
                    r.activity.mVisibleFromServer = true;
                    mNumVisibleActivities++;
                    if (r.activity.mVisibleFromClient) {
                        // 设置 View 可见 (当前逻辑)
                        r.activity.makeVisible();
                    }
                }
            } else {
                if (r.activity.mVisibleFromServer) {
                    r.activity.mVisibleFromServer = false;
                    mNumVisibleActivities--;
                    // 隐藏View
                    v.setVisibility(View.INVISIBLE);
                }
            }
        }
    }

当前是 onStart 逻辑,也看到了方法传递的参数是 true,说明要设置可见,所以会执行 Activity::makeVisible 逻辑。

ini 复制代码
# Activity

    void makeVisible() {
        if (!mWindowAdded) { // 之前setView时已置位true
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        // 设置可见
        mDecor.setVisibility(View.VISIBLE);
    }

2.5 onStart 小结

启动一个Activity 执行到 onStart 流程的分析就结束了,完整调用链如下:

arduino 复制代码
TransactionExecutor::cycleToPath
    TransactionExecutorHelper::getLifecyclePath
    TransactionExecutor::performLifecycleSequence
        ClientTransactionHandler::handleStartActivity
            ActivityThread::handleStartActivity
                Activity::performStart           -- onStart
                    Instrumentation::callActivityOnStart
                        Activity::onStart
                ActivityClientRecord::setState   -- 状态设置为 ON_START
                ActivityThread::updateVisibility -- 更新View可见性
                    Activity::makeVisible
                        View::setVisibility      -- VISIBLE

如果是按多任务键(Recent)再回到 Activity 是会执行 ActivityRecord::makeActiveIfNeeded 来构建 StartActivityItem 事务处理 onStart 流程,但是后续的逻辑还是一样的

我们知道 onStart 和 onStop 是成对的, 那 onStart 会执行 View::setVisibility 设置 View 可见,那相对的在 onStop 流程是不是就会 设置 View 不可见呢?

这个疑问留到下一篇 onStop 流程解答。

当前还是继续看 onResume 的执行

3. onResume

onResume 对应事务为 ResumeActivityItem

typescript 复制代码
# ResumeActivityItem

    @Override
    public void execute(ClientTransactionHandler client, ActivityClientRecord r,
            PendingTransactionActions pendingActions) {
            // Trace
            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
            // 应用端处理
            client.handleResumeActivity(r, true /* finalStateRequest */, mIsForward,
                    "RESUME_ACTIVITY");
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

    @Override
    public void postExecute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        // TODO(lifecycler): Use interface callback instead of actual implementation.
        ActivityClient.getInstance().activityResumed(token, client.isHandleSplashScreenExit(token));
    }

    @Override
    public int getTargetState() {
        return ON_RESUME;
    }

调用链如下:

arduino 复制代码
ResumeActivityItem::execute
    ActivityThread::handleResumeActivity
        ActivityThread::performResumeActivity   
            Activity::performResume     
                Instrumentation::callActivityOnResume
                    Activity::onResume           -- onResume
                ActivityClientRecord::setState   -- ON_RESUME
        WindowManagerImpl::addView               -- 创建ViewRootImpl
            WindowManagerGlobal::addView   
                ViewRootImpl::setView            -- 与WMS通信与WMS通信触发窗口的显示逻辑

开始撸代码。

ini 复制代码
# ActivityThread
    public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
            boolean isForward, String reason) {
        ......
        // 触发onResume
        if (!performResumeActivity(r, finalStateRequest, reason)) {
            return;
        }
        ......
        // 拿到activity
        final Activity a = r.activity;
        ......
        if (r.window == null && !a.mFinished && willBeVisible) {
            // 将本地的window设置到activityRecord中
            r.window = r.activity.getWindow();
            // 获取DecorView
            View decor = r.window.getDecorView();
            // 设置不可见  在后面调用Activity::makeVisible会设为可见
            decor.setVisibility(View.INVISIBLE);
            ViewManager wm = a.getWindowManager();
            // 获取参数
            WindowManager.LayoutParams l = r.window.getAttributes();
            // DecorView设置给Activity
            a.mDecor = decor;
            // 设置Activity的windowType,注意这个type,才是应用的窗口类型
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            ......
            if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    // 重点:执行addView,并设置mWindowAdded=true
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                } else {
                    a.onWindowAttributesChanged(l);
                }
            }

        } else if (!willBeVisible) {
            if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
            r.hideForNow = true;
        }
        ......
        r.nextIdle = mNewActivities;
        mNewActivities = r;
        // stop 逻辑的触发
        if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
        Looper.myQueue().addIdleHandler(new Idler());
    }

当前分析 onResume 生命周期,所以只看 performResumeActivity 方法就好。

typescript 复制代码
# ActivityThread

    @VisibleForTesting
    public boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
            String reason) {
            // log
            if (localLOGV) {
                Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished);
            }
                ......
                // 触发 onResume
                r.activity.performResume(r.startsNotResumed, reason);
                // 设置状态
                r.setState(ON_RESUME);
                ......
        }
# Activity
    final void performResume(boolean followedByPause, String reason) {
            // trace
            if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performResume:"
                        + mComponent.getClassName());
            }
            ......
            // 主流程
            mInstrumentation.callActivityOnResume(this);
            // wm_on_resume_called
            EventLogTags.writeWmOnResumeCalled(mIdent, getComponentName().getClassName(), reason);
            ......
            // Fragments 处理
            mFragments.dispatchResume();
            ......
    }

流程和其他的一样,也是先通过 Instrumentation 然后又回到 Activity 处理,然后打印另一个 events 日志。

ini 复制代码
# Instrumentation
    public void callActivityOnResume(Activity activity) {
        activity.mResumed = true;
        activity.onResume();
    }

4. 总结

SourceActivity 在启动过程中会执行的3个生命周期已经分析完了,当前分析的场景下有以下几个点:

    1. 这3个生命周期的执行的连续的,
    1. onStart 原来这个场景下不是通过事务执行的
    1. 知道了 Activity 生命周期事务跨进程处理方式
    1. DecorView 的可见性是在 onStart 设置的
    1. 执行 onResume 的时候会触发窗口的添加显示,从严格意义上说,执行 onResume 的时候并不意味着手机屏幕上就有UI数据了。(但是不那么严谨思考的话,正常情况下,onResume 执行了差不多窗口也就显示了)

关于 events 日志的整理如下:

    1. wm_restart_activity 的触发在 ActivityTaskSupervisor::realStartActivityLocked 方法构建2个事务的时候,表示 SystemService 端要真正触发 TargetActivity 启动
    1. wm_on_create_called 的触发在 Activity::performCreate 方法,表示TargetActivity端执行 onCreate
    1. wm_on_start_called 的触发在 Activity::performStart 方法,表示TargetActivity端执行 onStart
    1. wm_on_resume_called 的触发在 Activity::performResume 方法,表示TargetActivity端执行 onResume
相关推荐
还鮟1 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡2 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi002 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil4 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android
你过来啊你4 小时前
Android View的绘制原理详解
android
菌菇汤6 小时前
uni-app实现单选,多选也能搜索,勾选,选择,回显
前端·javascript·vue.js·微信小程序·uni-app·app
移动开发者1号7 小时前
使用 Android App Bundle 极致压缩应用体积
android·kotlin
移动开发者1号7 小时前
构建高可用线上性能监控体系:从原理到实战
android·kotlin
ii_best12 小时前
按键精灵支持安卓14、15系统,兼容64位环境开发辅助工具
android
美狐美颜sdk12 小时前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk