淺析Android Activity的啟動過程

LeBron_Six發表於2016-04-07

Activity作為Android的四大元件之一,也是最基本的元件,負責與使用者互動的所有功能。Activity的啟動過程也並非一件神祕的事情,接下來就簡單的從原始碼的角度分析一下Activity的啟動過程。

根Activity一般就是指我們專案中的MainActivity,代表了一個Android應用程式,一般也是在一個新的程式中啟動起來。在Android系統中,所有的Activity元件都儲存在堆疊中,我們啟動一個新的Activity元件就位於上一個Activity的上面。那麼我們從桌面(Launcher)開啟一個App是一個怎樣的過程呢,如下所示:

    (1)Launcher向ActivityManagerService傳送一個啟動MainActivity的請求;

    (2)ActivityManagerService首先將MainActivity的相關資訊儲存下來,然後向Launcher傳送一個使之進入中止狀態的請求;

    (3)Launcher收到中止狀態之後,就會想ActivityManagerService傳送一個已進入中止狀態的請求,便於ActivityManagerService繼續執行啟動MainActivity的操作;

    (4)ActivityManagerService檢查用於執行MainActivity的程式,如果不存在,則啟動一個新的程式;

    (5)新的應用程式程式啟動完成之後,就會向ActivityManagerService傳送一個啟動完成的請求,便於ActivityManagerService繼續執行啟動MainActivity的操作;

    (6)ActivityManagerService將第(2)步儲存下來的MainActivity相關資訊傳送給新建立的程式,便於該程式啟動MainActivity元件。

Launcher.startActivitySafely

boolean startActivitySafely(Intent intent, Object tag) {  
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
        try {  
            startActivity(intent);  
            return true;  
        } catch (ActivityNotFoundException e) {}  
}

當我們在Launcher上點選應用程式圖示時,startActivitySafely方法會被呼叫。需要啟動的Activity資訊儲存在intent中,包括action、category等等。那麼Launcher是如何獲得intent裡面的這些資訊呢?首先,系統在啟動時會啟動一個叫做PackageManagerService的管理服務,並且通過他來安裝系統中的應用程式,在這個過程中,PackageManagerService會對應用程式的配置檔案AndroidManifest.xml進行解析,從而得到程式裡的元件資訊(包括Activity、Service、Broadcast等),然後PackageManagerService去查詢所有action為“android.intent.action.MAIN”並且category為“android.intent.category.LAUNCHER”的Activity,然後為每個應用程式建立一個快捷方式圖示,並把程式資訊與之關聯。上述程式碼中,Activity的啟動標誌位設定為“Intent.FLAG_ACTIVITY_NEW_TASK”,便於他可以在一個新的任務中啟動。

Activity.startActivity

@Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            startActivityForResult(intent, -1);
        }
    }
呼叫startActivityForResult,第二個引數(requestCode)為-1則表示在Activity關閉時不需要將結果傳回來。

Activity.startActivityForResult

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) { //一般的Activity其mParent都為null
            Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this, 
                       mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);
            if (ar != null) { //傳送結果,即onActivityResult會被呼叫
                mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                        ar.getResultData());
            }
            if (requestCode >= 0) {
                mStartedActivity = true;
            }

            final View decor = mWindow != null ? mWindow.peekDecorView() : null;
            if (decor != null) {
                decor.cancelPendingInputEvents();
            }
        } else { //在ActivityGroup內部的Activity,內部處理邏輯和上面是類似的
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
        if (options != null && !isTopOfTask()) {
            mActivityTransitionState.startExitOutTransition(this, options);
        }
    }

不難發現,最後實際上是呼叫mInstrumentation.execStartActivity來啟動Activity,mInstrumentation型別為Instrumentation,用於監控程式和系統之間的互動操作。mInstrumentation代為執行Activity的啟動操作,便於他可以監控這一個互動過程。mMainThread的型別為ActivityThread,用於描述一個應用程式程式,系統每啟動一個程式都會在它裡面載入一個ActivityThread的例項,並且將該例項儲存在Activity的成員變數mMainThread中,而mMainThread.getApplicationThread()則用於獲取其內部一個型別為ApplicationThread的本地Binder物件。mToken的型別為IBinder,他是一個Binder的代理物件,只想了ActivityManagerService中一個型別為ActivityRecord的本地Binder物件。每一個已經啟動的Activity在ActivityManagerService中都有一個對應的ActivityRecord物件,用於維護Activity的執行狀態及資訊。

Instrumentation.execStartActivity

public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) { //先查詢一遍看是否存在這個activity
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options); //這裡才是真正開啟activity的地方,其核心功能在whoThread中完成。
            checkStartActivityResult(result, intent); // 處理各種異常,如ActivityNotFound
        } catch (RemoteException e) {
        }
        return null;
    }
上述程式碼可知,通過ActivityManagerNative.getDefault()獲取一個ActivityManagerService的代理物件,然後呼叫他的startActivity方法來通知ActivityManagerService去啟動Activity。

中間還有一系列過程,跟著原始碼走下去,不難發現,最後,是呼叫ApplicationThread的scheduleLaunchActivity來進行Activity的啟動。

Application.scheduleLaunchActivity

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

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            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);
        }

上述程式碼主要做的事就是構造一個ActivityClientRecord,然後呼叫sendMessage傳送一個訊息。在應用程式對應的程式中,每一個Activity元件都使用一個ActivityClientRecord物件來描述,他們儲存在ActivityThread類的成員變數mActivities中。那麼Handler是如何處理這個訊息的呢?

H.handleMessage

        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); // 處理訊息
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case RELAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                    handleRelaunchActivity(r);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case PAUSE_ACTIVITY:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
                            (msg.arg1&2) != 0);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                ... ...
        }

首先將msg裡面的obj轉成一個ActivityClientRecord物件,然後呼叫來獲取一個LoaderApk物件並儲存在ActivityClientRecord物件的成員變數packageInfo中。Loader物件用於描述一個已經載入的APK檔案。最後呼叫handleLaunchActivity來啟動Activity元件。

ActivityThread.handleLaunchActivity

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        if (r.profilerInfo != null) {
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }

        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

        WindowManagerGlobal.initialize();

        Activity a = performLaunchActivity(r, customIntent); //performLaunchActivity真正完成了activity的調起,Activity被例項化,onCreate被呼叫

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward, // 再呼叫Activity例項的Resume(使用者介面可見)
                    !r.activity.mFinished && !r.startsNotResumed);

            if (!r.activity.mFinished && r.startsNotResumed) {
                try {
                    r.activity.mCalled = false;
                    mInstrumentation.callActivityOnPause(r.activity); // finish的時候先調onPause
                    if (r.isPreHoneycomb()) {
                        r.state = oldState;
                    }
                    if (!r.activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPause()");
                    }

                } catch (SuperNotCalledException e) {
                    throw e;

                } catch (Exception e) {
                    if (!mInstrumentation.onException(r.activity, e)) {
                        throw new RuntimeException(
                                "Unable to pause activity "
                                + r.intent.getComponent().toShortString()
                                + ": " + e.toString(), e);
                    }
                }
                r.paused = true;
            }
        } else {
            try {
                ActivityManagerNative.getDefault() // finishActivity    一樣的原理
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
            } catch (RemoteException ex) {
            }
        }
    }
到了這一步,那就很清晰了。憋了一口氣到這裡,是不是突然放鬆了一下~~  再來看看performLaunchActivity做的事兒~~performLaunchActivity函式載入使用者自定義的Activity的派生類,並執行其onCreate函式,它將返回此Activity物件。

ActivityThread.performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }
        //從intent中取出目標activity的啟動引數(包名、類名等)
        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);
        }

        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); // 將Activity類檔案載入到記憶體中
            activity = mInstrumentation.newActivity( // 建立Activity例項
                    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);
            }
        }

        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity); // 初始化Context物件,作為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.referrer, r.voiceInteractor);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                if (r.isPersistable()) { //下面就是呼叫到acitivity的onCreate方法了
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                } // 至此,Activity啟動過程就結束了,其生命週期由ApplicationThread來管理
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }
                    if (!activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPostCreate()");
                    }
                }
            }
            r.paused = true;
            mActivities.put(r.token, r); // 將ActivityRecord物件儲存在ActivityThread的mActivities中
        } catch (SuperNotCalledException e) {
            throw e;
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to start activity " + component
                    + ": " + e.toString(), e);
            }
        }
        return activity;
    }

ActivityRecord裡面的token,是一個Binder的代理物件,和ActivityClientRecord物件一樣,都是用來描述所啟動的Activity元件,只不過前者是在ActivityManagerService中使用,後者是在應用程式程式中使用。

至此,Activity的啟動過程就分析完了。MainActivity的啟動過程,其實也可以認為是應用程式的啟動過程。

子Activity的啟動過程和根Activity的啟動過程也是類似的,過程如下:

    (1)MainActivity向ActivityManagerService傳送一個自動ChildActivity的請求;

    (2)ActivityManagerService首先將ChildActivity的資訊儲存下來,再向MainActivity傳送一箇中止的請求;

    (3)MainActivity收到請求進入中止狀態,告訴ActivityManagerService,便於ActivityManagerService繼續執行啟動ChildActivity的操作

    (4)ActivityManagerService檢查ChildActivity所執行的程式是否存在,存在就傳送ChildActivity資訊給他,以進行啟動。

原始碼方面,原理類似,相比起來會比MainActivity的稍微簡單一些,這裡就不再詳細敘述了,各位可以自行根據前面步驟,閱讀原始碼。

感謝閱讀~~

相關文章