1.Activity正常狀況下的生命週期的擴展學習筆記

1.1  啓動Activity的時候的特殊情況
       一般來說,用戶打開新的Activity或者切換到桌面的時候,回調如下: onPause->onStop。
      但是,如果Activity採用的是透明主題,那麼當前的Activity是不會回調onStop的。
1.2 被回收的Activity再次啓動
    當Activity被系統回收了以後再次打開,生命週期方法回調過程還是和第一次打開的一樣,但是,這只是說生命週期方法一樣,這不代表所有的過程都一樣。
1.3 Activity生命週期的對稱性
    從整個生命週期來說,onCreate對應於onDestory,onResume對應onPause ,onStart對應onRestart.其中,前者只能有一次調用,而後者可以多次調用。
1.4 onResume和onStart,onPause和onStop看似相似,卻有不同
    onStart和onResume,onPause和onStop從描述上看是差不多的,但是,卻是有着一些實質性的不同。
    這裏面實質性的不同,就是他們所處的生命週期的不同,onStart、onStop表示的是,Activity是否可見,而onResume、onPause則是從是否運行在前臺的角度來處理的,從可靠性來說,onPause是比onStop更加可靠的。

1.5 不同Activity的onResume和onPause誰先誰後?
    假設當前Activity爲A,接下來要打開一個新的ActivityB,那麼B的onResume和A的onPause哪個先執行呢?
    這個需要從Activity源碼那邊開始入手,Activity的啓動過程,涉及到了Instrumentation、ActivityThread和ActivityManagerService(AMS).
    Activity的啓動請求會通過Instructmentation來處理,然後Instructmentation通過Biner向AMS發出請求,AMS內部維護着一個ActivityStack,並且負責棧內的Activity的狀態同步,AMS通過ActivityThread去同步Activity的狀態,完成生命週期方法的調用。
    在ActivityStatck(com.android.server.am包中)中的resumeTopActivityInnerLocked方法中,有這樣一段代碼:
    
       // We need to start pausing the current activity so the top one
        // can be resumed...
        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving);
        if (mResumedActivity != null) {
            pausing = true;
            startPausingLocked(userLeaving, false);
            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
        }
     if (pausing) {
            if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG,
                    "resumeTopActivityLocked: Skip resume: need to start pausing");
            // At this point we want to put the upcoming activity's process
            // at the top of the LRU list, since we know we will be needing it
            // very soon and it would be a waste to let it get killed if it
            // happens to be sitting towards the end.
            if (next.app != null && next.app.thread != null) {
                // No reason to do full oom adj update here; we'll let that
                // happen whenever it needs to later.
                mService.updateLruProcessLocked(next.app, false, true);
            }
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return true;
        }

    從上述代碼可以看出,在新Activity啓動之前,棧頂的Activity需要先onPause纔會啓動新的Activity.最終,在ActivityStatckSupervisor中的realStartActivityLocked方法毀調用下面這個代碼:
     app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    new Configuration(mService.mConfiguration), r.compat,
                    app.repProcState, r.icicle, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profileFile, profileFd,
                    profileAutoStop);
    上面代碼中的app類型爲:ProcessRecord 。
     查看ProcessRecord 中thread的代碼:
    IApplicationThread thread;  // the actual proc...  may be null only if
                                // 'persistent' is true (in which case we
                                // are in the process of launching the app)
可以知道,類型爲IApplicationThread,上面說具體實現就是在App運行的進程中,那麼可以知道這個代碼的具體實現就是在ActivityThread,所以實際上調用的是ActivityThread的scheduleLauchActivity方法,而scheduleLauchActivity方法最終會完成新Activity的onCreate、onStart、onResume的調用過程,
    具體代碼如下:
    
     public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
                int procState, Bundle state, List<ResultInfo> pendingResults,
                List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
                String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

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

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

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

            r.profileFile = profileName;
            r.profileFd = profileFd;
            r.autoStopProfiler = autoStopProfiler;

            updatePendingConfiguration(curConfig);

            queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
        }
    其中:
       queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
    上面這一行會通過一個類型爲:H(命名我mH)的Handler對象接收到消息以後,在handlerLaunchActivity方法中來實現新Activity的onCreate、onStart、onResume。
    所以結論得出:舊的Activity先onPause,新的Activity再啓動。

1.6 關於onPause的解釋:
    Android官方文檔在onPause中標註瞭如下:
    
      When activity B is launched in front of activity A, this callback will  be invoked on A.  B will not be created until A's {@link #onPause} returns, so be sure to not do anything lengthy here.
    意思就是不要在onPause中做耗時的操作,因爲新的Activity會在onPause以後纔開始顯示到前臺。因此耗時操作應該放在onStop中,(onStop不會影響新的Activity的顯示)onPause適合做一些保存應用當前的運行數據、如果沒有足夠多的資源去啓動新的Activity那麼更要持久化數據,並且在這裏最好暫停一些動畫啊等消耗CPU資源的操作,使得下一個Activity可以快速啓動起來。或者關閉一些唯一的單獨的資源訪問接口,比如說關閉調用相機。
本文參考任玉剛先生的《Anroid開發藝術探索》書和官方文檔。
    
發佈了30 篇原創文章 · 獲贊 17 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章