Activity生命週期全解析

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爲空,我們需要額外判斷是否爲空

以上。如有錯誤不足的地方歡迎指出,隨時改正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章