1. 程式人生 > >Activity 啟動流程

Activity 啟動流程

Activity 啟動呼叫流程 (基於5.0原始碼)

我們從 startActivity 開始:

startActivity()

startActivity()方法有多個過載,但是都會呼叫到 startActivityResult:

 public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            ...
// } ...// 省略大量程式碼 }

Ok,我們可以看到 呼叫到了 Instrumentation 的 execStartActivity 方法。

下面我們看一下 execStartActivity 中的兩行重點程式碼:

int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded
(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); checkStartActivityResult(result, intent);

可以看到,呼叫到了 ActivityManagerNative.getDefault() 的 startActivity。 而getDefault()返回的是一個 IActivityManager.

checkStartActivityResult()是校驗activity 的啟動結果的,比如我們沒有在androidManifest 註冊,等等。就會丟擲異常。

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

可以看到是一個單例。IActivityManager 是一個 Binder 介面

public interface IActivityManager extends IInterface {
    ...// 方法
}

而該Binder 的真正實現 是 ActivityManagerService(簡稱 AMS) 。 所以接下來我們來看 AMS 中的 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 options) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
    }

啥實事也沒幹,直接轉調了 startActivityAsUser 繼續跟進,

 @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, userId, null, null);
    }

該方法調了 ActivityStackSupervisorstartActivityMayWait 方法。 在該方法中又呼叫了自身的 startActivityLocked 方法,該方法中又呼叫到 startActivityUncheckedLocked() 又從該方法呼叫到了 ActivityStack 的 resumeTopActivityLocked 方法。這時 已經從 ActivityStackSupervisor 轉到了 ActivityStack

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        if (inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            inResumeTopActivity = true;
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            inResumeTopActivity = false;
        }
        return result;
    }

上面程式碼看到 resumeTopActivityLocked 呼叫了 resumeTopActivityInnerLocked 在該方法中:

  mStackSupervisor.startSpecificActivityLocked(next, true, false);

又回到了 ActivityStackSupervisor 中, ok, startSpecificActivityLocked 中 呼叫了 realStartActivityLocked 看到這個名字,說明我們已經差不多了。 該方法的關鍵程式碼如下:

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState,
                    results, newIntents, !andResume, mService.isNextTransitionForward(),
                    profilerInfo);

那麼app.thread 是什麼呢?? 它是 IApplicationThread 型別。

public interface IApplicationThread extends IInterface {}

是一個Binder 介面。 AMS程序通過該 binder介面 來呼叫 app程序的方法。

IApplicationThread 的實現 是在 ActivityThread 中的 ApplicationThread , IApplicationThread 中定義了很多介面方法。都是和四大元件相關的

    void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,
            int configChanges, boolean dontReport) throws RemoteException;
    void scheduleStopActivity(IBinder token, boolean showWindow,
            int configChanges) throws RemoteException;
    void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
    void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;
    void scheduleResumeActivity(IBinder token, int procState, boolean isForward, Bundle resumeArgs)
            throws RemoteException;
    void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
    void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
            IVoiceInteractor voiceInteractor, int procState, Bundle state,
            PersistableBundle persistentState, List<ResultInfo> pendingResults,
            List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
            ProfilerInfo profilerInfo) throws RemoteException;
    void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
            List<Intent> pendingNewIntents, int configChanges,
            boolean notResumed, Configuration config) throws RemoteException;
    void scheduleNewIntent(List<Intent> intent, IBinder token) throws RemoteException;

    ......

ok 我們來看 ApplicationThread 的實現.

 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
                IVoiceInteractor voiceInteractor, int procState, Bundle state,
                PersistableBundle persistentState, List<ResultInfo> pendingResults,
                List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
                ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profilerInfo = profilerInfo;

            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

scheduleLaunchActivity 中儲存了啟動Activity的相關資訊,然後 傳送了一個訊息 H.LAUNCH_ACTIVITY 這裡呢,我們就需要提一下這個 H .

 final H mH = new H();

H 繼承自Handler。負責系統訊息的處理。 訊息的處理是在 handleMessage 方法中。 至於這裡為什麼要使用Handler 。 因為之前的操作 都是在服務端的 Binder 執行緒池中,所以我們這裡需要切換到主執行緒。 handleMessage中的 呼叫了 handleLaunchActivity 方法。 而該方法 又呼叫了 performLaunchActivity方法.

該方法中做了如下幾件事:

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 物件

        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.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);
            }
        }

3.通過LoadedApk 的 makeApplication 方法來嘗試建立 Application物件。

4.建立ContextImpl 物件並通過Activity 的 attach 方法來完成一些重要資料的初始化

  Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.voiceInteractor);

ContextImpl 是context 的具體實現,Context 中的大部分邏輯都是由 ContextImpl 來實現的。 ContextImpl 是通過 Activity 的 attach 方法 來和 Activity 建立關聯的。 而且 attach 方法中 還會完成 Window 的建立 並建立和 Winwod 的關聯。 這樣當Window 接收到外部輸入事件後就可以傳遞給Activity 了。

5.呼叫Activity 的 OnCreate 方法。

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

整體總結:

當啟動一個Activity時,會通過 Instrumentation 類來 execStartActivity來啟動,該類 可以看作是一個管家。裡面有很多 關於 Activity 生命週期的方法,可以看作是一箇中間件。 在該方法中會 呼叫 IActivityManager 中的 startActivity 。該介面是個Binder介面,真正的實現是 服務端的 AMS, 在ams 中會 涉及到兩個類 ActivityStackSupervisor 和 ActivityStack 處理 Activity 相關的啟動邏輯。 當準備好後, 會呼叫 app.thread.scheduleLaunchActivity(). app.thread 的型別是 IApplicationThread 介面,是個Binder 介面。真正的實現類是 ApplicationThread 。 在 scheduleLaunchActivity 中進行了資料的儲存,然後傳送 LAUNCH_ACTIVITY 的訊息,由 H 。 H 繼承自Handler。 此處由於AMS 端的呼叫是在 binder 執行緒池,所以要切換到主執行緒。 在 handleMessage 中進行了相關的 Activity的建立、初始化、以及 OnCreate 的呼叫。

簡記:

Handler 在Android 中執行緒通訊起著很大的作用, Framework 層有很多的Handler,執行在不同的執行緒; 而我們應用層也有一個比較重要的Handler,即 ActivityThread 中的 mH. 執行在 ui 執行緒。

ApplicationThread 為 IApplicationThread 的具體實現類, 用來接收服務端的訊息, 四大元件就是通過 ApplicationThread 來接收服務端的訊息的。

ActivityStarter 處理一些 intent 和 flag 。 然後交給ActivityStackSupervisor 和 ActivityStack 來處理被呼叫Activity 的程序進棧。 如果被呼叫者的程序存在,就會使用 ApplicationThread 這個客戶端的 Binder 通知已存在的呼叫者程序啟動Activity, 如果不存在,就會使用 Socket 通知 Zygote 程序 fork 出一個程序,用來承載即將啟動的Activity。

ActivityStarter : intent 和 flag 如何開啟Activity

ActivityStack: 管理Activity

ActivityStack 管理Activity的方法:

startActivityLocked()
resumeTopActivityLocked()
completeResumeLocked()
startPausingLocked()
completePauseLocked()
stopActivityLocked()
activityPausedLocked()
finishActivityLocked()
activityDestroyedLocked()