上面是Activity典型的生命週期流程圖,基本的就不講了,提兩個問題來求解下
1:當啓動一個新的Activity時,新舊兩個Activity的生命週期執行順序
2:當你在onCreat中調用startActivity或者finish的時候,生命週期執行流程
首先來求解第一個問題,很簡單,建立兩個Activity,每個生命週期上打上log
@Override
protected void onStart() {
Log.e("xw", "111---onStart");
super.onStart();
}
@Override
protected void onStart() {
Log.e("xw", "222---onStart");
super.onStart();
}
跳轉之後log爲
可以看到首先調用了第一個Activity的onPause方法,之後第二個Activity的onCreat,onStart,onResume方法依次執行,最後才輪到第一個Activity的onStop方法。
先不從實現單從產品的角度來講,這種執行順序很有道理,因爲onPause執行後意味着Activity不再接收事件,所以onPause必定要在第二個Activity的onResume方法之前執行,否則會導致有兩個Activity可以接收事件,這顯然不合理。而各種系統都要考慮的就是響應速度,從安卓來講,就是要最快的展示給用戶新的Activity,也就是新的Activity的生命週期要儘早執行,所以,最終結論是,首先終止第一個Activity接收事件的能力,之後展現新的Activity,最後第一個Activity再去進行收尾工作。具體的實現等下再說。
接着是第二個問題,首先看調用startActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.e("xw", "111---onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startActivity(new Intent(MainActivity.this, Main2Activity.class));
}
打印的log爲
可以看到完整的執行了整個生命週期,而且第一個onPause首先執行,接着是finish
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.e("xw", "111---onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
finish();
}
可以看到只執行了onCreate和與之對應的onDestroy,那麼我們把finish放在onStart中,看看會發生什麼
@Override
protected void onStart() {
Log.e("xw", "111---onStart");
finish();
super.onStart();
}
可以看到,同樣如此,沒有完整的執行整個生命週期
下面我們開始分析原因
首先我們要知道Activity的生命週期調用是由Framework中的AMS決定的,我們看看到底請求如何從應用傳遞到AMS
startActivity最終都會調用到startActivityForResult這個方法中,我們看看他做了什麼
@Override
public void startActivityForResult(
String who, Intent intent, int requestCode, @Nullable Bundle options) {
Uri referrer = onProvideReferrer();
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, who,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, who, requestCode,
ar.getResultCode(), ar.getResultData());
}
cancelInputsAndStartExitTransition(options);
}
關鍵在於mInstrumentation的execStartActivity方法
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String target,
Intent intent, int requestCode, Bundle options) {
......
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target, requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
其中ActivityManagerNative.getDefault()獲取的就是AMS的代理類,我們可以利用它遠程調用AMS的各種方法,在這裏,我們將調用AMS的startActivity,這樣請求就從應用傳遞給了AMS
接着看看finish方法
public void finish() {
finish(DONT_FINISH_TASK_WITH_ACTIVITY);
}
private void finish(int finishTask) {
if (mParent == null) {
int resultCode;
Intent resultData;
synchronized (this) {
resultCode = mResultCode;
resultData = mResultData;
}
if (false) Log.v(TAG, "Finishing self: token=" + mToken);
try {
if (resultData != null) {
resultData.prepareToLeaveProcess(this);
}
if (ActivityManagerNative.getDefault()
.finishActivity(mToken, resultCode, resultData, finishTask)) {
mFinished = true;
}
} catch (RemoteException e) {
// Empty
}
} else {
mParent.finishFromChild(this);
}
}
也是利用ActivityManagerNative.getDefault()將請求傳遞給了AMS
AMS收到消息後根據請求內部進行一系列操作,之後也是通過IPC調用,將需要的操作通知應用進程。
應用進程其實就是一個ActivityThread,而負責接收AMS消息的則是ActivityThread的一個內部類ApplicationThread,他也是一個binder,它裏面的方法中很明顯的有幾個涉及基本的生命週期調用
scheduleLaunchActivity
scheduleResumeActivity
schedulePauseActivity
scheduleStopActivity
scheduleDestroyActivity
其中scheduleLaunchActivity適用於新建一個Activity,scheduleResumeActivity適用將已有的Activity重新展示,schedulePauseActivity由於之前所說的原因所以會單獨調用,scheduleStopActivity適用於startActivity時舊的Activity,而scheduleDestroyActivity適用於finish是舊的Activity,可以看到也是除了schedulePauseActivity較爲特殊,也是一一對應的關係。
下面我們看看scheduleLaunchActivity的具體實現
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
......
sendMessage(H.LAUNCH_ACTIVITY, r);
}
因爲binder的代碼會運行在他開啓的線程中,所以要使用Handler將消息發送到主線程中,利用ActivityThread中H這個Handler來進行處理,看看H的處理方式
case LAUNCH_ACTIVITY: {
......
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
} break;
調用到handleLaunchActivity方法中
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
......
Activity a = performLaunchActivity(r, customIntent);
......
handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
......
}
關鍵的就是這兩個,先看第一句performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
......
} ......
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);
......
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
......
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
......
return activity;
}
重要的以下四點:
1:根據傳遞進的參數利用ClassLoader構建Activity類
2:調用Activity的attach的方法,裏面將Activity的各種參數初始化,並且設置了Activity關聯的PhoneWindow類,很重要,但是和現在講的生命週期關係不大
3:mInstrumentation.callActivityOnCreate方法,在裏面Activity調用了我們熟悉的onCreat方法
4:activity.performStart()裏面調用了Activity的onStart方法,當然要調用的首先會判斷mFinished的值,我們再看下前面的finish方法,裏面在將消息發送給AMS後還將mFinished置爲TRUE,這解釋了爲什麼在onCreat調用finish後onStart方法不會被調用到。在調用完onStart之後還會將stopped置爲false,這個將之後用於判斷是否去執行onStop方法
看完performLaunchActivity,我們接着去看看handleResumeActivity方法,從名字就可以看出是用來調用onResume方法的
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
......
r = performResumeActivity(token, clearHide, reason);
......
ActivityManagerNative.getDefault().activityResumed(token);
}
public final ActivityClientRecord performResumeActivity(IBinder token,
boolean clearHide, String reason) {
......
if (r != null && !r.activity.mFinished) {
......
r.activity.performResume();
r.paused = false;
r.stopped = false;
......
}
return r;
}
也會判斷mFinished的值,之後調用onResume。
如果正常情況下的話,scheduleLaunchActivity會使一個新的Activity對象被創建,並且成功調用onCreate,onStart,onResume方法,並將paused 和stopped 值置爲false,最後將成功啓動Activity的消息通知AMS
所以同理scheduleResumeActivity會去執行Activity的onStart和onResume方法,scheduleStopActivity和scheduleDestroyActivity也同樣,拿schedulePauseActivity做個代表再說下,schedulePauseActivity發消息後會執行ActivityThread的handlePauseActivity方法
private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport, int seq) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
......
performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
......
ActivityManagerNative.getDefault().activityPaused(token);
}
}
同樣,調用performPauseActivity然後去通知AMS,看看performPauseActivity方法
final Bundle performPauseActivity(IBinder token, boolean finished,
boolean saveState, String reason) {
ActivityClientRecord r = mActivities.get(token);
return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
}
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
boolean saveState, String reason) {
if (r.paused) {
if (r.activity.mFinished) {
// If we are finishing, we won't call onResume() in certain cases.
// So here we likewise don't want to call onPause() if the activity
// isn't resumed.
return null;
}
.....
}
.....
performPauseActivityIfNeeded(r, reason);
......
}
首先就告訴我們如果調用了finish但是沒有調過onResume那麼就什麼都不做,直接返回,否則的話就會去調用performPauseActivityIfNeeded,裏面會調用Activity的onPause方法。