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開發藝術探索》書和官方文檔。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.