Activity作爲Android四大組件之一,重要性不言而喻。本文主要分析四種情況下Activity的生命週期,相信看完會有更深刻全面的理解。
1.正常情況下的生命週期
正常情況下的生命週期是指在有用戶參與的情況下,Activity所經過的生命週期 的改變。
public abstract class BaseActivity extends Activity {
private Unbinder mUnBinder;
protected abstract int getLayoutId();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
mUnBinder = ButterKnife.bind(this);
Log.e("tag", this.getClass().getName() + "生命週期:onCreate");
}
@Override
protected void onStart() {
super.onStart();
Log.e("tag", this.getClass().getName() + "生命週期:onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.e("tag", this.getClass().getName() + "生命週期:onResume");
}
@Override
protected void onRestart() {
super.onRestart();
Log.e("tag", this.getClass().getName() + "生命週期:onRestart");
}
@Override
protected void onPause() {
super.onPause();
Log.e("tag", this.getClass().getName() + "生命週期:onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.e("tag", this.getClass().getName() + "生命週期:onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
mUnBinder.unbind();
Log.e("tag", this.getClass().getName() + "生命週期:onDestroy");
}
}
第一次啓動MainActivity,生命週期回調如下:
onCreate:創建Activity,只會調用一次
onStart:啓動Activity,沒有出現在前臺,無法和用戶交互
onResume:顯示Activity,出現在前臺並開始活動
打開一個新的SecondActivity或者將應用切換到後臺,生命週期回調如下:
onPause:暫停Activity
onStop:停止Activity
有一種特殊情況,如果新Activity採用了透明主題,那麼當前Activity不會回調onStop
返回舊的MainActivity或者將應用切換到前臺,生命週期回調如下:
onRestart:重啓Activity
最後按返回鍵退出這個應用,生命週期回調如下:
onDestroy:銷燬Activity
假如應用已經被切換到後臺,這時直接結束所有進程,生命週期回調如下:
從整個生命週期來說,onCreate和onDestroy是配對的,分別標識着Activity的創建和銷燬,並且只可能有一次被調用。從Activity是否可見來說,onStart和onStop是配對的,隨着用戶的操作或者設備屏幕的點亮和熄滅,這兩個方法可能被調用多次;從Activity是否在前臺來說,onResume和onPause是配對的,隨着用戶的操作或者設備屏幕的點亮和熄滅,這兩個方法可能被調用多次。
2.彈出Dialog下的生命週期
Activity中存在彈出Dialog的情況下,從前臺切換到後臺,再從後臺切換到前臺,MainActivity的生命週期回調如下:
3.Activity跳轉下的生命週期
從MainActivity跳轉到SecondActivity,兩個Activity的生命週期執行順序:
可以看到,新啓動一個Activity的時候,舊Activity的onPause會先執行,然後纔會啓動新的Activity。通過分析這個問題,我們知道不能在舊Activity的onPause中做複雜耗時的操作,因爲必須onPause執行完成以後新Activity才能顯示。
4.異常情況下的生命週期
最常見的一種情況就是屏幕旋轉導致的Activity的生命週期的改變。
MainActivity的配置文件不設置任何參數,從豎屏切換到橫屏:
調用了一次完整的生命週期
MainActivity的配置文件不設置任何參數,從橫屏切換到豎屏:
調用了一次完整的生命週期,並沒有調用兩次
MainActivity的配置文件添加:
android:configChanges="orientation|keyboardHidden"
從豎屏切換到橫屏或者從橫屏切換到豎屏:
調用了一次完整的生命週期,參數設置無效。原因在於當targetSdkVersion小於等於12時,不會調用完整生命週期;當targetSdkVersion大於12時,會調用一次完整生命週期。
那麼該怎樣設置才能在targetSdkVersion大於12的時候,橫豎屏切換不調用生命週期呢:
android:configChanges="orientation|keyboardHidden|screenSize"
可以看到參數設置有效,沒有調用生命週期。onConfigurationChanged()中我們可以處理想要的業務邏輯。
OK,我們已經知道這種系統配置發生變化的情況會調用Activity的完整生命週期。在這種Activity被異常中止的情況下,系統會調用onSaveInstanceState來保存當前Activity的狀態,正常情況下系統不會回調這個方法。繼續往下看:
首先在MainActivity的配置文件中刪除剛纔添加的android:configChanges
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
Log.e("tag", "onCreate中獲取保存的值爲:" + savedInstanceState.get("data"));
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.e("tag", "onSaveInstanceState()方法被調用");
outState.putString("data", "我是需要保存的值");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.e("tag", "onRestoreInstanceState中獲取保存的值爲:" + savedInstanceState.get("data"));
}
正常啓動MainActivity,生命週期回調如下:
當我從豎屏切換到橫屏時:
這種異常情況下調用了onSaveInstanceState()方法,我們如果需要在這種異常情況下保存一些必要的參數,可以把這些參數以鍵值對的形式保存在onSaveInstanceState方法中。怎樣恢復這些數據呢,恢復數據的位置有兩種:onRestoreInstanceState和onCreate,區別如下:
onRestoreInstanceState一旦被調用,其參數Bundle savedInstanceState一定是有值的,我們不用額外判斷是否爲空
onCreate如果正常啓動的話,其參數Bundle savedInstanceState爲空,我們需要額外判斷是否爲空
以上。如有錯誤不足的地方歡迎指出,隨時改正。