概要:
生命週期主要包含 6 種狀態: onCreat, onStart, onResume, onPause, onStop, onDestroy。
各種狀態意義為
onCreate 代表 Activity 的建立
onStart 代表 Activity 的啟動
onResume 代表 Activity 的恢復
onPause 代表 Activity 的暫停
onStop 代表 Activity 的停止
onDestroy 代表 Activity 的銷毀
這些狀態分別互相配對,構成 3 種生命週期,分別為完整的生命週期,可視的生命週期,前台的生命週期。
完整的生命週期包含可視的生命週期,可視的生命週期包含前台的生命週期。
完整的生命週期:
Activity 從建立到銷毀的全部過程。最外層生命週期,生命週期發生在 onCreate 到 onDestroy 之間。
可視的生命週期:
Activity 從使用者可視到離開使用者視線的過程。生命週期發生在 onStart 到 onStop 之間。注意可視包含該 Activity 被其它元件遮蓋只顯示一部分的情況。
前台的生命週期:
Activity 顯示在所有的元件之前並可與使用者互動。生命週期發生在 onResume 到 onPause 之間。
另外還有 4 種特殊的生命週期狀態,各為 onRestart, onSaveInstanceState, on RestoreInstanceState, onNewIntent。
onRestart 的呼叫點為從 onStop 到 onStart 之間,也就是 onStop -> onRestart -> onStart。
onSaveInstanceState 用於儲存 Activity 的資料。
onNewIntent 只有在 LaunchMode 為 SingleTop 且啟動的 Activity 為符合重用該 Activity 的規則時才會被呼叫。(onNewIntent -> onResume)
為了實際了解生命週期的變化,建立 FirstActivity 並覆寫所有生命週期印出 Log
FirstActivity.java
public class FirstActivity extends AppCompatActivity implements OnClickListener {
private static final String TAG = FirstActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, TAG + " onCreate");
setContentView(R.layout.first_activity);
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, TAG + " onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, TAG + " onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, TAG + " onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, TAG + " onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, TAG + " onDestroy");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, TAG + " onRestart");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, TAG + " onSaveInstanceState");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(TAG, TAG + " onRestoreInstanceState");
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d(TAG, TAG + " onNewIntent");
}
}
紀錄1
使用者點擊 back key, home key, menu key 所觸發的生命週期變化:
A.啟動 FirstActivity 後點擊 back key 關閉 FirstActivity
1.點擊 App icon 啟動 FirstActivity:
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.點擊 back key:
D: FirstActivity onPause
D: FirstActivity onStop
D: FirstActivity onDestroy
B.啟動 FirstActivity 後點擊 home key
1.點擊App icon 啟動 FirstActivity:
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.點擊 home key:
D: FirstActivity onPause
D: FirstActivity onSaveInstanceState
D: FirstActivity onStop
C.啟動 FirstActivity 後點擊 home key 再點擊 App icon
1.點擊 App icon 啟動 FirstActivity:
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.點擊 home key:
D: FirstActivity onPause
D: FirstActivity onSaveInstanceState
D: FirstActivity onStop
3.點擊 App icon:
D: FirstActivity onRestart
D: FirstActivity onStart
D: FirstActivity onResume
D.啟動 FirstActivity 後點擊 home key 再點擊 menu key 再拖曳移除 App頁面
1.點擊 App icon 啟動 FirstActivity:
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.點擊 home key:
D: FirstActivity onPause
D: FirstActivity onSaveInstanceState
D: FirstActivity onStop
3.點擊 menu key,拖曳移除 App:
D: FirstActivity onDestroy(注意有時候不會顯示)
E.啟動 FirstActivit y後點擊 home key 再點擊 menu key 再點擊 App 頁面
1.點擊 App icon 啟動 FirstActivity:
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.點擊 home key:
D: FirstActivity onPause
D: FirstActivity onSaveInstanceState
D: FirstActivity onStop
3.點擊 menu key 並點擊 App 頁面:
D: FirstActivity onRestart
D: FirstActivity onStart
D: FirstActivity onResume
F.啟動 FirstActivity後點擊 menu key
1.點擊 App icon 啟動 FirstActivity:
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.點擊 menu key:
D: FirstActivity onPause
D: FirstActivity onSaveInstanceState
D: FirstActivity onStop
G.啟動 FirstActivity 後點擊 menu key 再拖曳移除 App
1.點擊 App icon 啟動 FirstActivity:
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.點擊 menu key:
D: FirstActivity onPause
D: FirstActivity onSaveInstanceState
D: FirstActivity onStop
3.拖曳移除 App:
沒有顯示Log , 推測應該呼叫onDestroy
H.啟動 FirstActivity 後點擊 menu key 再點擊 App頁面
1.點擊 App icon 啟動 FirstActivity:
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.點擊 menu key:
D: FirstActivity onPause
D: FirstActivity onSaveInstanceState
D: FirstActivity onStop
3.點擊 App 頁面:
D: FirstActivity onRestart
D: FirstActivity onStart
D: FirstActivity onResume
重點:
1.按下 home key 和 menu key 都會觸發 onSaveInstanceState (在 onPause 之後),但按下 back key 不會觸發 onSaveInstanceState。
2.當 Activity 從後台回到前台都會觸發 onRestart -> onStart -> onResume
紀錄2
Activity之間切換的生命週期變化:
2.1修改 FirstActivity,加入啟動 SecondActivity 的功能。
FirstActivity.java
public class FirstActivity extends AppCompatActivity implements OnClickListener {
…
private Button mLaunchSecondBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, TAG + " onCreate");
setContentView(R.layout.first_activity);
initUI();
}
private void initUI() {
mLaunchSecondBtn = findViewById(R.id.first_activity_launch);
mLaunchSecondBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
int uiID = v.getId();
switch (uiID) {
case R.id.first_activity_launch_second_activity:
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
finish();
break;
}
}
2.2 新增 SecondActivity 和 FirstActivity 互相切換來觀察生命週期。
SecondActivity.java
public class SecondActivity extends AppCompatActivity implements OnClickListener {
private static final String TAG = SecondActivity.class.getSimpleName();
private Button mLaunchFirstBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, TAG + " onCreate");
setContentView(R.layout.second_activity);
initUI();
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, TAG + " onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, TAG + " onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, TAG + " onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, TAG + " onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, TAG + " onDestroy");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, TAG + " onRestart");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, TAG + " onSaveInstanceState");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(TAG, TAG + " onRestoreInstanceState");
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d(TAG, TAG + " onNewIntent");
}
private void initUI() {
mLaunchFirstBtn = findViewById(R.id.second_activity_launch_first_activity);
mLaunchFirstBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
int uiID = v.getId();
switch (uiID) {
case R.id.second_activity_launch_first_activity:
Intent intent = new Intent(this,FirstActivity.class);
startActivity(intent);
finish();
break;
}
}
}
A.FirstActivity 啟動 SecondActivity (FirstActivity 不會 finish),再關閉 SecondActivity,再關閉 FirstActivity
1.點擊 App icon 啟動 FirstActivity:
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.點擊 FirstActivity 的按鈕啟動 SecondActivity。注意 FirstActivity 沒有 finish
D: FirstActivity onPause
D: SecondActivity onCreate
D: SecondActivity onStart
D: SecondActivity onResume
D: FirstActivity onSaveInstanceState
D: FirstActivity onStop
3.點擊 back key 關閉 SecondActivity,讓 FirstActivity 回到前台
D: SecondActivity onPause
D: FirstActivity onRestart
D: FirstActivity onStart
D: FirstActivity onResume
D: SecondActivity onStop
D: SecondActivity onDestroy
4.點擊 back key 關閉 FirstActivity
D: FirstActivity onPause
D: FirstActivity onStop
D: FirstActivity onDestroy
B.FirstActivity 啟動 SecondActivity(FirstActivity 會 finish),再關閉 SecondActivity
1.點擊 App icon 啟動 FristActivity:
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.點擊 FirstActivity 的按鈕啟動 SecondActivity。注意 FristActivity 會 finish
D: FirstActivity onPause
D: SecondActivity onCreate
D: SecondActivity onStart
D: SecondActivity onResume
D: FirstActivity onStop
D: FirstActivity onDestroy
3.按下 back key 關閉 SecondActivity
D: SecondActivity onPause
D: SecondActivity onStop
D: SecondActivity onDestroy
C.FirstActivity 啟動 SecondActivity(FirstActivity 不會 finish), SecondActivity 再啟動 FirstActivity (SecondActivity不會finish)
1.點擊 App icon 啟動 FristActivity:
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.點擊 FirstActivity 的按鈕啟動 SecondActivity。注意 FirstActivity 不會 finish
D: FirstActivity onPause
D: SecondActivity onCreate
D: SecondActivity onStart
D: SecondActivity onResume
D: FirstActivity onSaveInstanceState
D: FirstActivity onStop
3.點擊 SecondActivity 的按鈕啟動 FirstActivity。注意 SecondActivity 不會 finish
D: SecondActivity onPause
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
D: SecondActivity onSaveInstanceState
D: SecondActivity onStop
D.FirstActivity 啟動 SecondActivity,注意 SecondActivity 使用透明主題(FirstActivity 不會 finish), SecondActivity在啟動 FirstActivity(SecondActivity 不會 finish)
1.點擊 App icon 啟動 FristActivity:
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.點擊 FirstActivity 的按鈕啟動 SecondActivity(注意 SecondActivity 使用透明主題注意 FirstActivity不會 finish)
D: FirstActivity onPause
D: SecondActivity onCreate
D: SecondActivity onStart
D: SecondActivity onResume
D: FirstActivity onSaveInstanceState
3.點擊 SecondActivity 的按鈕啟動 FirstActivity。注意 SecondActivity 不會 finish
D: SecondActivity onPause
D: FirstActivity onStop
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
D: SecondActivity onSaveInstanceState
D: SecondActivity onStop
重點:
1.當第 1 個 Activity 啟動第 2 個 Activity時,會讓第 1 個 Activity先呼叫完 onPause,再進行第 2 個 Activity 的初始化(onCreate -> onStart -> onResume)直到第 2 個 Activity 呼叫完 onResume 之後再進行第 1 個 Activity 的後續動作。
2.當第 1 個 Activity 啟動第 2 個 Activity 時,若第 1 個 Activity 會 finish,則 onSaveInstanceState 不會被呼叫。動作順序如下
(第 1 個 Activity 啟動第 2 個 Activity)
Activity1 onPause
Activity2 onCreate
Activity2 onStart
Activity2 onResume
Activity1 onStop
Activity1 onDestroy
反之,若第 1 個Activity 不會 finish,則 onSaveInstanceState 會在 onStop 之前被呼叫。
(第 1 個 Activity 啟動第 2 個 Activity)
Activity1 onPause
Activity2 onCreate
Activity2 onStart
Activity2 onResume
Activity1 onSaveInstanceState
Activity1 onStop
3.如果要啟動的 Activity(SecondActivity)是透明主題,則啟動者(FirstActivity)啟動 SecondActivity 之後不會呼叫 onStop,如下
(當 FirstActivity 啟動 SecondActivity 之後)
D: FirstActivity onPause
D: SecondActivity onCreate
D: SecondActivity onStart
D: SecondActivity onResume
D: FirstActivity onSaveInstanceState
而當 SecondActivity 啟動 FirstActivity之後才會呼叫 onStop 如下
D: SecondActivity onPause
D: FirstActivity onStop
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
D: SecondActivity onSaveInstanceState
D: SecondActivity onStop
紀錄3.
系統配置改變所造成的生命週期變化
當系統配置發生改變,Activity 就會觸發重建過程,最常見的系統配置發生變化為旋轉螢幕。因為這種生命週期變化為系統控制,所以當觸發 onSaveInstanceState 時也會一併呼叫 onRestoreInstanceState 來恢復資料。
A.啟動 FirstActivity 後旋轉螢幕
1.點擊 App icon 啟動 FirstActivity:
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.旋轉螢幕觸發從直屏到橫屏導致 FirstActivity 重建
D: FirstActivity onPause
D: FirstActivity onSaveInstanceState
D: FirstActivity onStop
D: FirstActivity onDestroy
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onRestoreInstanceState
D: FirstActivity onResume
3.再次旋轉螢幕從橫屏到直屏導致 FristActivity 重建
D: FirstActivity onPause
D: FirstActivity onSaveInstanceState
D: FirstActivity onStop
D: FirstActivity onDestroy
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onRestoreInstanceState
D: FirstActivity onResume
重點:
1.注意旋轉螢幕之後 onSaveInstanceState 會在 onPause 之後呼叫,而 onRestoreInstanceState 會在 onStart 之後呼叫。
2.若 Activity 要恢復資料可以選擇 onCreate 或 onRestoreInstanceState,差別為於在 onCreate 中需要判斷傳入的參數 Bundle 是否為空,如果是空則不需要恢復資料,而非空才需要進行恢復資料的動作。如下
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
if(savedInstanceState != null){
// restore data
}
}
3.若要支援旋轉螢幕,但不重建 Activity,可以在 AndroidManifest.xml 中對該 Activity 設定為
android:configChanges="orientation|screenSize"
如此,旋轉螢幕之後 Activity 還是會切換直橫屏,但不會重建,資料也不會初始化,在這種情況下若想在旋轉螢幕時收到通知,可在 Activity 覆寫以下方法。(注意該方法只有在 android:configChanges="orientation|screenSize" 被設定時才呼叫)。如下
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d(TAG, "newConfig.toString():"+newConfig.toString());
}
測試生命週期如下
1.點擊 App icon 啟動 FirstActivity
D: FirstActivity onCreate
D: FirstActivity onStart
D: FirstActivity onResume
2.旋轉螢幕從直屏轉為橫屏
D: newConfig.toString():{0 1.0 ?mcc?mnc zh_TW ldltr sw360dp w640dp h335dp
320dpi nrml long land finger -keyb/v/h -nav/h s.47}
3.旋轉螢幕從橫屏轉為直屏
D: newConfig.toString():{0 1.0 ?mcc?mnc zh_TW ldltr sw360dp w360dp h615dp 320dpi nrml long port finger -keyb/v/h -nav/h s.48}
4.若想保持螢幕為直屏或橫屏,可在 AndroidManifest.xml 的 Activity 加入以下
android:screenOrientation="portrait"
螢幕便會保持直屏不會旋轉。
5.注意 onRestoreInstanceState 僅用於系統配置變化時(如旋轉螢幕)導致的重建。如果是使用者導致的重建(點擊 back key or home key)則需要在 onCreate 恢復資料。
注意以上 Activity 的生命週期實驗都是以 LaunchMode (啟動模式)為 default,在其它的啟動模式(SingleTop, SingleTask, SingleInstance)則另外需要另外紀錄。
Orignal From: Activity 生命週期紀錄
0 意見:
張貼留言