Android V app 冷启动(9) Activity 生命周期调度

目前,Transition 动画显示的是启动窗口,而不是 Activity 的真窗。如果要显示 Activity 真窗,首先需要在 app 端创建 Activity,此时 Activity 会添加 View,在 View 完成绘制后,才会通过 WMS 端显示出来。

本文分析 app 端是如何完成 Activity 生命周期调度,重点关注 Activity 生命周期是何时何地执行的,以及如何完成添加 Activity View 的,其他的细节,将会被忽略。

根据 Android V app 冷启动 (1) Activity生命周期 可知,在第三阶段启动中,通过 ActivityTaskSupervisor#realStartActivityLocked() 通知 app 端启动 Activity,如下

java 复制代码
// ActivityTaskSupervisor.java

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
        boolean andResume, boolean checkConfig) throws RemoteException {

    // ...

    try {
        // ...
        
        try {
            
            // ...

            // 创建回调
            final LaunchActivityItem launchActivityItem = LaunchActivityItem.obtain(r.token,
                    r.intent, System.identityHashCode(r), r.info,
                    procConfig, overrideConfig, deviceId,
                    r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
                    proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
                    results, newIntents, r.takeSceneTransitionInfo(), isTransitionForward,
                    proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
                    r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken,
                    r.initialCallerInfoAccessToken, activityWindowInfo);

            final ActivityLifecycleItem lifecycleItem;
            if (andResume) {
                // 创建生命周期请求
                lifecycleItem = ResumeActivityItem.obtain(r.token, isTransitionForward,
                        r.shouldSendCompatFakeFocus());
            } 
            
            // ...

            // 通知 app 端启动 Activity
            mService.getLifecycleManager().scheduleTransactionAndLifecycleItems(
                    proc.getThread(), launchActivityItem, lifecycleItem,
                    // Immediately dispatch the transaction, so that if it fails, the server can
                    // restart the process and retry now.
                    true /* shouldDispatchImmediately */);

            // ...

        } catch (RemoteException e) {
            // ...
        }
    } finally {
        // ...
    }

    // ...

    return true;
}

我在 Android U WMS: 屏幕旋转动画(2) app 侧 activity relaunch 分析过 Activity 生命周期调度框架。在这里,LaunchActivityItem 是回调,ResumeActivityItem 是生命周期请求,app 端执行流程如下

  1. 执行 LaunchActivityItem 和 ResumeActivityItem 的 preExecute()。本文不分析这一步,因为与 Activity 生命周期关联不大。
  2. 执行回调 LaunchActivityItem 的 execute() 和 postExecute()。这里会创建 Activity,并调用 Activity#onCreate()。
  3. 把生命周期执行到 onStart(),然后执行 ResumeActivityItem 的 execute() 和 postExecute()。在 execute() 中,会把 Activity 生命周期执行到 onResume()。

create activity

LaunchActivityItem#execute() 会创建 Activity,并执行 Activity#onCreate(),如下

java 复制代码
// LaunchActivityItem.java

public void execute(@NonNull ClientTransactionHandler client,
        @NonNull PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    
    final ActivityClientRecord r = new ActivityClientRecord(mActivityToken, mIntent, mIdent,
            mInfo, mOverrideConfig, mReferrer, mVoiceInteractor, mState, mPersistentState,
            mPendingResults, mPendingNewIntents, mSceneTransitionInfo, mIsForward,
            mProfilerInfo, client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
            mTaskFragmentToken, mInitialCallerInfoAccessToken, mActivityWindowInfo);
    
    // 调用 ActivityThread#handleLaunchActivity()
    client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */);
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
java 复制代码
// ActivityThread.java

public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, int deviceId, Intent customIntent) {
    // ...
    
    final Activity a = performLaunchActivity(r, customIntent);

    // ...

    return a;
}



private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // ...
    
    Activity activity = null;
    try {
        // ...
        
        // 1. 通过反射创建 Activity 对象
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        
        // ...
    } catch (Exception e) {
        // ...
    }

    try {
        // 2. 创建 Application 对象,并调用其 onCreate()
        Application app = r.packageInfo.makeApplicationInner(false, mInstrumentation);

        // ...

        if (activity != null) {
            // ...
            
            // 3. attach activity
            activity.attach(activityBaseContext, 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, r.initialCallerInfoAccessToken);

            // ...
            
            if (r.isPersistable()) {
                
            } else {
                // 4. 调用 Activity#onCreate()
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            
            // ...
        }
        
        r.setState(ON_CREATE);

    } catch (SuperNotCalledException e) {
       // ...
    }

    return activity;
}

attach Activity 主要是为 Activity 创建 Window,如下

java 复制代码
// Activity.java

final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor,
        Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
        IBinder shareableActivityToken, IBinder initialCallerInfoAccessToken) {
    // ...

    // 1. 创建 Window
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    
    // ...
    
    // 2. Window 保存 WindowManager
    // WindowManager 实现类为 WindowManagerImpl
    mWindow.setWindowManager(
            (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
            mToken, mComponent.flattenToString(),
            (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    // ...
    mWindowManager = mWindow.getWindowManager();
    
    // ...
}

在执行 Activity#onCreate() 时, 会通过 setContentView() 来创建 Activity View,并保存到 PhoneWindow 中的 DecorView 下,如下

java 复制代码
// Activity.java

public void setContentView(@LayoutRes int layoutResID) {
    // 由 Window 保存 Activity View
    getWindow().setContentView(layoutResID);
    
    // ...
}
java 复制代码
// PhoneWindow.java

public void setContentView(int layoutResID) {
    if (mContentParent == null) {
        // 创建 DecorView
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        
    }

    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {

    } else {
        // 把 Activity View 保存到 DecorView 下
        mLayoutInflater.inflate(layoutResID, mContentParent);
    }
    
    mContentParent.requestApplyInsets();
    
    // ...
}

start activity

ResumeActivityItem 定义的目标生命周期是 RESUMED,但是目前生命周期只执行到 onCreate()。因此,需要把生命周期执行到 onStart(),如下

java 复制代码
// ActivityThread.java

public void handleStartActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, SceneTransitionInfo sceneTransitionInfo) {
    final Activity activity = r.activity;
    
    // ...

    // Start
    activity.performStart("handleStartActivity");
    r.setState(ON_START);

    if (pendingActions == null) {
        return;
    }

    // Restore instance state
    if (pendingActions.shouldRestoreInstanceState()) {
       
    }

    // Call postOnCreate()
    if (pendingActions.shouldCallOnPostCreate()) {
       
    }
    
    // 此时 Activity 还没有创建 DecoView,这里无法更新其可见性
    updateVisibility(r, true /* show */);
    mSomeActivitiesChanged = true;
}



final void performStart(String reason) {
    // activity start trace
    if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performStart:"
                + mComponent.getClassName());
    }
    
    // ...
    
    // 执行 Activity#onStart()
    mInstrumentation.callActivityOnStart(this);
    
    // ...
    
    // activity start event log : wm_on_start_called
    EventLogTags.writeWmOnStartCalled(mIdent, getComponentName().getClassName(), reason,
            duration);

    //...
    
    Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}

resume activity

ResumeActivityItem#execute() 会把 Activity 生命周期执行到 onResumed(),如下

java 复制代码
// ResumeActivityItem.java

public void execute(@NonNull ClientTransactionHandler client, @NonNull ActivityClientRecord r,
        @NonNull PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
    client.handleResumeActivity(r, true /* finalStateRequest */, mIsForward,
            mShouldSendCompatFakeFocus, "RESUME_ACTIVITY");
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
java 复制代码
// ActivityThread.java

public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
        boolean isForward, boolean shouldSendCompatFakeFocus, String reason) {
    // ...
    
    // 1. 执行 resume activity
    if (!performResumeActivity(r, finalStateRequest, reason)) {
        return;
    }
    
    // ...

    final Activity a = r.activity;

    // ...

    // a.mStartedActivity 表示是否从当前 Activity 启动另外一个 activity
    // willBeVisible 此时为 true
    boolean willBeVisible = !a.mStartedActivity;
    
    // ...
    
    if (r.window == null && !a.mFinished && willBeVisible) {
        // 此时 ActivityClientRecord#window 才保存了 Activity 创建的 PhoneWindow
        r.window = r.activity.getWindow();
        
        // DecorView 的可见性,先设置为 INVISIBLE
        View decor = r.window.getDecorView();
        decor.setVisibility(View.INVISIBLE);
        
        // 2. 通过 Activity 创建的 WindowManager 来添加 DecorView
        ViewManager wm = a.getWindowManager();
        WindowManager.LayoutParams l = r.window.getAttributes();
        a.mDecor = decor;
        l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
        l.softInputMode |= forwardBit;
        // ...
        if (a.mVisibleFromClient) {
            if (!a.mWindowAdded) {
                a.mWindowAdded = true;
                wm.addView(decor, l);
            } else {
                
            }
        }

        // ...
    } else if (!willBeVisible) {

    }

    // ...

    // 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 (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward);
        
        // ...
        
        r.activity.mVisibleFromServer = true;
        mNumVisibleActivities++;
        
        if (r.activity.mVisibleFromClient) {
            // 3. 把 DecorView 设置为 VISIBLE
            r.activity.makeVisible();
        }

        // ...
    }

    mNewActivities.add(r);
    
    if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
    Looper.myQueue().addIdleHandler(new Idler());
}

首先看下如何执行 Activity#onResumed() 生命周期,如下

java 复制代码
// ActivityThread.java

public boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
        String reason) {
    // ...
    
    try {
        // ...
        
        r.activity.performResume(r.startsNotResumed, reason);

        r.state = null;
        r.persistentState = null;
        r.setState(ON_RESUME);

        reportTopResumedActivityChanged(r, r.isTopResumedActivity, "topWhenResuming");
    } catch (Exception e) {
        
    }
    return true;
}
java 复制代码
// Activity.java

final void performResume(boolean followedByPause, String reason) {
    if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performResume:"
                + mComponent.getClassName());
    }
    
    // ...
    
    
    // 执行 Activity#onResume()
    mInstrumentation.callActivityOnResume(this);
    
    // activity resume 的 event log
    EventLogTags.writeWmOnResumeCalled(mIdent, getComponentName().getClassName(), reason,
            duration);
    
    // ...
    
    Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}

Activity 生命周期执行到 RESUMED 后,会通过 Activity 创建的 WindowManager 添加 DecoreView,如下

java 复制代码
// WindowManagerImpl.java

public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyTokens(params);
    
    // 由 WindowManagerGlobal 完成 add view
    mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
            mContext.getUserId());
}
java 复制代码
// WindowManagerGlobal.java

public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow, int userId) {
    // ...

    ViewRootImpl root;
    View panelParentView = null;

    synchronized (mLock) {
        // ....

        if (windowlessSession == null) {
            // 1. 创建 ViewRootImpl
            root = new ViewRootImpl(view.getContext(), display);
        } else {
            // ...
        }

        view.setLayoutParams(wparams);

        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);

        // do this last because it fires off messages to start doing things
        try {
            // 2. 通过 ViewRootImpl 保存 DecorView
            root.setView(view, wparams, panelParentView, userId);
        } catch (RuntimeException e) {
           
        }
    }
}

ViewRootImpl 保存 DecorView 后,就会对它进行 measure,layout,draw。

相关推荐
geovindu13 小时前
sql:Search-Optimized SQL Queries using mysql 9.0
android·数据库·sql·mysql·数据库开发·数据库架构
知之则吱吱15 小时前
Android 开发者验证机制迎来新变化:核心要求、实施时间与开发者应对指南
android·google
墨天梦16 小时前
D09_Retrofit接口与数据转换
android·kotlin·retrofit
电商API_1800790524717 小时前
闲鱼商品列表API接口商品详情API接口请求示例(含一份真实响应数据示例)
android·数据挖掘·网络爬虫·跨境电商·反向海淘
我命由我1234518 小时前
Android 广播 - 组件通信
android·java·开发语言·android studio·android jetpack·android-studio·android runtime
阿俊-全栈开发18 小时前
LikeShop 单商户标准版商品管理二开:分类、SKU 规格与库存联动实现
android·likeshop·likeshop开源商城
用户21816970493021 小时前
Kotlin 语法二
android
妖星21 小时前
android 源码分析surfaceFinger是如何通过设置属性启动bootanim
android
JoyMonitor21 小时前
APK mmap 内存增长定位:pagemap 与 DEX 结构联合定位方法
android