Activity的啓動流程梳理

Activity的啓動流程梳理

本文目標

  • 本文章對 startActivity 的啓動流程,進行總體把握
  • 本文章基於Android-28

整體流程圖
Activity的啓動流程.png

1.startActivity方法

分析的入口,我們啓動一個頁面時調用startActivity方法

startActivity(Intent(this, DemoActivity::class.java))

點進去看一下

Activity#startActivity

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        startActivityForResult(intent, -1);
    }
}

層層調用,最終會走到

Activity#startActivityForResult

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity( //1 Instrumentation類
                    this, mMainThread.getApplicationThread(), mToken, this,//2
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            ...
        } else {
            ...
        }
    }
  • 調用 Instrumentation.execStartActivity 方法。剩下的交給 Instrumentation 類去處理。Instrumentation 類主要用來監控應用程序與系統交互

  • mMainThread 是 ActivityThread 類型,ActivityThread 可以理解爲一個進程

  • mMainThread 獲取一個 ApplicationThread 的引用,這個引用就是用來實現進程間通信的

2.Instrumentation類

至此,啓動就交給了Instrumentation類的execStartActivity方法了

Instrumentation#execStartActivity

 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
       
        ...

        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService() //1獲取AMS
                .startActivity(whoThread, who.getBasePackageName(), intent,//2調用AMS方法
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);//3 檢查啓動Activity的結果,會拋異常
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

  • ActivityManager.getService().startActivity方法
  • ActivityManger.getService 獲取 AMS 的實例

看一下代碼,單例模式對外提供AMS其實是一個Binder

ActivityManager#getService

public static IActivityManager getService() {
    return IActivityManagerSingleton.get();//獲取AMS
}

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;
            }
        };

這裏就是通過 AIDL 來調用 AMS 的 startActivity 方法

startActivity 的工作重心成功移到了系統進程 AMS 中。

3.ActivityManagerService類

ActivityManagerService#startActivity

@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
  				//層層調用startActivityAsUser方法
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}

層層調用startActivityAsUser方法

ActivityManagerService#startActivityAsUser

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
        boolean validateIncomingUser) {
    enforceNotIsolatedCaller("startActivity");

    userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
            Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

    //1  獲取一個ActivityStarter
    return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
            .setCaller(caller)
            .setCallingPackage(callingPackage)
            .setResolvedType(resolvedType)
            .setResultTo(resultTo)
            .setResultWho(resultWho)
            .setRequestCode(requestCode)
            .setStartFlags(startFlags)
            .setProfilerInfo(profilerInfo)
            .setActivityOptions(bOptions)
            .setMayWait(userId)
            .execute();//2 調用execute()

}
  • mActivityStartController.obtainStarter 獲取一個ActivityStarter並調用execute()
  • execute()中會調用ActivityStarter的startActivityMayWait方法

注意;此時轉移到ActivityStarter中

4.ActivityStarter類

ActivityStarter#startActivityMayWait


 private int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
            int userId, TaskRecord inTask, String reason,
            boolean allowPendingRemoteAnimationRegistryLookup) {
       
       ...

        //通過ActivityStackSupervisor 獲取 ResolveInfo
        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
                0 /* matchFlags */,
                        computeResolveFilterUid(
                                callingUid, realCallingUid, mRequest.filterCallingUid));
       ...
        //通過ActivityStackSupervisor 獲取 Activity
        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

        ...

            final ActivityRecord[] outRecord = new ActivityRecord[1];
   					//1 startActivity
            int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                    allowPendingRemoteAnimationRegistryLookup);

        ...
            return res;
        }
    }

在 startActivityMayWait 方法中調用了一個重載的 startActivity 方法,

層層重載調用(想看的自己閱讀源碼,我這裏就不貼了)

最終會調用的 ActivityStarter 中的 startActivityUnchecked 方法來獲取啓動 Activity 的結果

ActivityStarter#startActivityUnchecked

 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {

        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor);

        //計算啓動 Activity 的 Flag 值
   			//不同的 Flag 決定了啓動 Activity 最終會被放置到哪一個 Task 集合中。
        computeLaunchingTaskFlags();

        computeSourceStack();

        mIntent.setFlags(mLaunchFlags);

        ...

        // 處理 Task 和 Activity 的進棧操作。
        mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
                mOptions);
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                ...
            } else {
               
                //啓動棧中頂部的 Activity。
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else if (mStartActivity != null) {
            mSupervisor.mRecentTasks.add(mStartActivity.getTask());
        }
        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

        mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
                preferredLaunchDisplayId, mTargetStack);

        return START_SUCCESS;
    }

注意

  • mTargetStack.startActivityLocked方法

  • mSupervisor.resumeFocusedStackTopActivityLocked方法

此時轉移到ActivityStack中

5.ActivityStack類

首先看

ActivityStack#startActivityLocked

void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
            boolean newTask, boolean keepCurTransition, ActivityOptions options) {
        TaskRecord rTask = r.getTask();
        final int taskId = rTask.taskId;
        // mLaunchTaskBehind tasks get placed at the back of the task stack.
        if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
           
            // 將 Task 和 Activity 入棧
            insertTaskAtTop(rTask, r);
        }
      
      ...
    }

方法中會調用 insertTaskAtTop 方法嘗試將 Task 和 Activity 入棧

接下來調用mSupervisor.resumeFocusedStackTopActivityLocked方法

6.ActivityStackSupervisor類

ActivityStackSupervisor#resumeFocusedStackTopActivityLocked

    boolean resumeFocusedStackTopActivityLocked() {
        return resumeFocusedStackTopActivityLocked(null, null, null);
    }

    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

        if (!readyToResume()) {
            return false;
        }

        if (targetStack != null && isFocusedStack(targetStack)) {
          	//resumeTopActivityUncheckedLocked方法
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }

        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || !r.isState(RESUMED)) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        } else if (r.isState(RESUMED)) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }

        return false;
    }

**注意:**targetStack.resumeTopActivityUncheckedLocked方法

調用再次轉到ActivityStack中

7.ActivityStack類

ActivityStack#resumeTopActivityUncheckedLocked

 boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mStackSupervisor.inResumeTopActivity) {
           
            return false;
        }

        boolean result = false;
        try {
      
            mStackSupervisor.inResumeTopActivity = true;
            //調用 resumeTopActivityInnerLocked
            result = resumeTopActivityInnerLocked(prev, options);

            final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
            if (next == null || !next.canTurnScreenOn()) {
                checkReadyForSleep();
            }
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }

        return result;
    }

ActivityStack#resumeTopActivityInnerLocked

 boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        
        ...
        //調用
        mStackSupervisor.startSpecificActivityLocked(next, true, true);

        ...

    }

最終代碼又回到了 ActivityStackSupervisor 中的 startSpecificActivityLocked 方法。

8.ActivityStackSupervisor類

ActivityStackSupervisor#startSpecificActivityLocked

void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // 根據進程名稱和 Application 的 uid 來判斷目標進程是否已經創建,
        // 如果沒有則代表進程未創建。
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        getLaunchTimeTracker().setLaunchTime(r);

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
          
                    app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
                            mService.mProcessStats);
                }
                //關鍵方法 來執行啓動 Activity 的操作
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
               ...
            }
        }

        // 處調用 AMS 創建 Activity 所在進程
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

具體請看註釋

接下來執行realStartActivityLocked方法

ActivityStackSupervisor#realStartActivityLocked

    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {

        ...

        try {
           
            ...

                // 創建 Activity 啓動事務,並傳入 app.thread 參數
                final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                        r.appToken);
          			//重點
                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                        System.identityHashCode(r), r.info,
                       
                        mergedConfiguration.getGlobalConfiguration(),   
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                        r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                        profilerInfo));

                // Set desired final state.
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
                } else {
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);

                // 執行 Activity 啓動事務 獲取ClientLifecycleManager執行事務
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);

                ...

        return true;
    }

  

接下來調用ClientLifecycleManager scheduleTransaction方法

9.ClientLifecycleManager類

ClientLifecycleManager#scheduleTransaction

 void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        transaction.schedule();
        if (!(client instanceof Binder)) {
            transaction.recycle();
        }
    }

實際調用了

ClientTransaction#schedule

public void schedule() throws RemoteException {
		//mClient是 ApplicationThread
    mClient.scheduleTransaction(this);
}

可以看出實際上是調用了啓動事務 ClientTransaction 的 schedule 方法,而這個 transaction 實際上是在創建 ClientTransaction 時傳入的 app.thread 對象,也就是 ApplicationThread

**重點 mClient是什麼時候賦值的?**mClient是在 ActivityStackSupervisor#realStartActivityLocked方法中

ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,r.appToken);

獲取ClientTransaction時賦值的(具體的自己看下代碼就瞭然了)

總結

  • 這裏傳入的 app.thread 會賦值給 ClientTransaction 的成員變量 mClient,ClientTransaction 會調用 mClient.scheduleTransaction(this) 來執行事務。
  • 這個 app.thread 是 ActivityThread 的內部類 ApplicationThread,所以事務最終是調用 app.thread 的 scheduleTransaction 執行。

此時 AMS 通過進程間通信機制通知 ApplicationThread 執行

回個神

接下來就要去看 mClient.scheduleTransaction(this) 這個方法了

也就是ApplicationThread

10.ApplicationThread類

說明一下ApplicationThread是 ActivityThread 的內部類

首先看事務執行的方法

ApplicationThread#scheduleTransaction

   @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            ActivityThread.this.scheduleTransaction(transaction);
        }

好嘛,調用的是ActivityThread的scheduleTransaction方法

然鵝,你Command+F12找不到這個方法

去看下ActivityThread繼承ClientTransactionHandler

public final class ActivityThread extends ClientTransactionHandler {

去看父類ClientTransactionHandler

ClientTransactionHandler#scheduleTransaction

public abstract class ClientTransactionHandler {

    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
      	// Android消息機制
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
  
}

調用 sendMessage 方法,向 Handler 中發送了一個 EXECUTE_TRANSACTION 的消息,並且 Message 中的 obj 就是啓動 Activity 的事務對象。而這個 Handler 的具體實現是 ActivityThread 中的 mH 對象

內部類

H#handleMessage

 class H extends Handler {

    public void handleMessage(Message msg) {
            
            switch (msg.what) {
                case EXECUTE_TRANSACTION:
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
                		// TransactionExecutor 類
                    mTransactionExecutor.execute(transaction);
                    if (isSystem()) {
                        transaction.recycle();
                    }
                    break;

            }

 }

11.TransactionExecutor類

TransactionExecutor#execute

public void execute(ClientTransaction transaction) {
    final IBinder token = transaction.getActivityToken();
		//
    executeCallbacks(transaction);

    executeLifecycleState(transaction);
    mPendingActions.clear();
}

TransactionExecutor#executeCallbacks

  public void executeCallbacks(ClientTransaction transaction) {
        final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
        ....
       
        final int size = callbacks.size();
        for (int i = 0; i < size; ++i) {
            final ClientTransactionItem item = callbacks.get(i);
           
            // item 執行
            item.execute(mTransactionHandler, token, mPendingActions);
            item.postExecute(mTransactionHandler, token, mPendingActions);
           
            if (postExecutionState != UNDEFINED && r != null) {
                final boolean shouldExcludeLastTransition =
                        i == lastCallbackRequestingState && finalState == postExecutionState;
                cycleToPath(r, postExecutionState, shouldExcludeLastTransition);
            }
        }
    }

在 executeCallback 方法中,會遍歷事務中的 callback 並執行 execute 方法,這些 callbacks 是何時被添加的呢?

還記得 ClientTransaction 是如何創建被創建的嗎?

請看ActivityStackSupervisor#realStartActivityLocked這個方法

clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent)...

加入的是LaunchActivityItem

所有看LaunchActivityItem的 execute方法

12.LaunchActivityItem類

@Override
public void execute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
            mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
            mPendingResults, mPendingNewIntents, mIsForward,
            mProfilerInfo, client);
  	//終於看到曙光了 handleLaunchActivity
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

終於到了跟 Activity 生命週期相關的方法了,圖中 client 是 ClientTransationHandler 類型,實際實現類就是 ActivityThread。因此最終方法又回到了 ActivityThread。

也就是 ActivityThread的handleLaunchActivity方法

13.ActivityThread類

ActivityThread#handleLaunchActivity

  public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        
        ...
        //初始化WindowManagerGlobal
        WindowManagerGlobal.initialize();
				//調用 performLaunchActivity 創建並顯示 Activity
        final Activity a = performLaunchActivity(r, customIntent);

        ...

        return a;
    }

  • WindowManagerGlobal.initialize();這個方法後面會分析 Window、Activity、View 三者之間的關係這個類很重要

調用performLaunchActivity

    /**  Core implementation of activity launch. */
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        
        ...

        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            //通過反射創建目標 Activity 對象
            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) {
            ...
        }

        try {
            //重要方法 僅會創建一個Application
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (activity != null) {

                appContext.setOuterContext(activity);

                // 調用 attach 方法建立 Activity 與 Context 之間的聯繫,
                // 創建 PhoneWindow 對象,並與 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);

               ...

                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    //通過 Instrumentation 最終調用 Activity 的 onCreate 方法。
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
              

        return activity;
    }

至此,目標 Activity 已經被成功創建並執行生命週期方法

原文地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章