Activity 關於生命週期一些問題的實踐驗證

Activity 關於生命週期一些問題的實踐驗證

本文內容
1. 如何驗證問題
2. 正常情況下的生命週期
3. 由活動 A 啓動活動 B 時,活動 A 的 onpause() 和 B 的 onResume() 哪一個先執行?
4. dialog 是否會對生命週期產生影響?
    4.1 標準的 AlertDialog 是否有影響?
    4.2 全屏的 AlertDialog 是否有影響?
    4.3 主題爲 Dialog 的 Activity 是否有影響?
5. 橫豎屏切換時生命週期變化
6. 內存不足殺死 Activity 時的生命週期變化
7. 異常情況下數據保存
8. 異常情況下,系統默認恢復 EditText 的文本信息
9. 異常情況下,系統默認恢復 TextView 的文本信息
10. 防止重建

1. 如何驗證問題

  創建一個 MainActivity 、 FirstActivity 類以及一些驗證問題的 Dialog 等等其他的類,MainActivity 是項目的主界面。MainActivity 與 FirstActivity 的生命週期方法中都打印了日誌。
  相關驗證代碼在:activityproject

2. 正常情況下的生命週期

  • 點擊應用到界面顯示出來的生命週期

    結論:第一次打開 MainActivity ,調用了 onCreate() -> onStart() -> onResume() 方法。

  • 按下電源鍵時的屏保的生命週期

    結論:屏保時的生命週期調用爲:onPause() -> onStop() 。

  • 亮屏時的生命週期

    結論:亮屏時的生命週期調用爲:onRestore() -> onStart() -> onResume() 。

  • 按 home 鍵時的生命週期

    結論:按下 home 鍵時的生命週期調用爲:onPause() -> onStop() 。

  • 按 home 鍵後重新打開界面的生命週期(從後臺應用打開的生命週期是相同的)

    結論:按下 home 鍵之後重新打開界面時的生命週期調用爲:onRestore() -> onStart() -> onResume() 。

  • 在顯示界面點擊返回鍵退出的生命週期

    結論:關閉 MainActivity ,調用了 onPause() -> onStop() -> onDestory() 方法。

3. 由活動A啓動活動B時。活動A的 onPause() 與活動B的 onResume() 哪一個先執行?

  在 MainActivity 界面中添加一個按鈕,點擊按鈕跳轉 FirstActivity 界面。

  • 打開 MainActivity 界面,在 MainActivity 跳轉到 FirstAcivity ,運行結果如下:

  可以看到,是 MainActivity 先執行了 onPause() , FirstActivity 的 onResume() 後執行的。

  • 點擊返回看一下執行的順序:

  點擊返回後,可以看到是 FirstActivity 的 onPause() 先執行,MainActivity 的 onResume() 後執行。

結論:當活動 A 啓動活動 B 時,是活動 A 的 onPause() 方法先執行,活動 B 的 onResume() 方法後執行。

4.dialog 是否會對生命週期產生影響?

  查看 Activity 生命週期的描述,如果 Activity 不在前臺,且並非完全不可見時, Activity 就會處在 onPause() 的暫停狀態。但是事實如何,用代碼說話,測試三種情況:一,彈出標準的 AlertDialog ;二,彈出全屏的 AlertDialog ;三,彈出主題爲 Theme.AppCompat.Dialog 的 Activity ,查看這三種情況下的生命週期的變化:

4.1 標準的 AlertDialog 是否有影響?

  在 MainActivity 的佈局中添加一個彈出標準 AlertDialog 的按鈕,用於觀察 MainActivity 在彈出 AlertDialog 和隱藏 AlertDialog 的情況下的生命週期變化。

  • 點擊彈出標準 AlertDialog 的生命週期的運行

      可以看到彈出標準的 AlertDialog 並不會對 MainActivity 的生命週期有任何的影響。

  • 點擊 AlertDialog 的“確定”按鈕,對 AlertDialog 進行隱藏,觀察 MainActivity 的生命週期的變化
      點擊 AlertDialog 的“確定”按鈕後,看到沒有任何的日誌打印出來,所有隱藏標準 AlertDialog 也不會對 MainActivity 的生命週期有任何的影響。

結論:顯示和隱藏標準的 AlertDialog 不會對 MainActivity 的生命週期有任何的影響。

4.2 全屏的 AlertDialog 是否有影響?

  在 MainActivity 的佈局中添加一個彈出全屏 AlertDialog 的按鈕,用於觀察 MainActivity 在彈出全屏 AlertDialog 和隱藏全屏 AlertDialog 的情況下的生命週期變化。

  • 點擊彈出全屏 AlertDialog 的生命週期的運行

      可以看到彈出全屏的 AlertDialog 並不會對 MainActivity 的生命週期有任何的影響。

  • 點擊 AlertDialog 的“確定”按鈕,對 AlertDialog 進行隱藏,觀察 MainActivity 的生命週期的變化
      點擊 AlertDialog 的“確定”按鈕後,看到沒有任何的日誌打印出來,所有隱藏全屏 AlertDialog 也不會對 MainActivity 的生命週期有任何的影響。

結論:顯示和隱藏全屏的 AlertDialog 不會對 MainActivity 的生命週期有任何的影響。

4.3 主題爲 Dialog 的 Activity 是否有影響?

  在 MainActivity 的佈局中添加一個跳轉主題爲 Theme.AppCompat.Dialog 的 Activity 的按鈕,用於觀察 MainActivity 在跳轉主題爲 Theme.AppCompat.Dialog 的 Activity 和從 主題爲 Theme.AppCompat.Dialog 的 Activity 返回的情況下的生命週期變化。

  • 跳轉主題爲 Dialog 的 Activity 的生命週期變化

      可以看到跳轉主題爲 Dialog 的 Activity 會對 MainActivity 的生命週期產生影響,生命週期的變化與跳轉 Activity 的變化相同。

  • 在主題爲 Dialog 的 Activity 下點擊返回鍵的生命週期變化

      在主題爲 Dialog 的 Activity 下點擊返回鍵,返回到 MainActivity 的界面,從運行結果可以看出,與跳轉 Activity 之後返回的聲明週期變化不同,MainActivity 只調用了 onResume() 方法,並沒有調用 onRestart() 與 onStart() 兩個方法,DialogActivity 調用 onPause()、onStop() 與 onDestory() 方法。

結論:主題爲 Dialog 的 Activity 會對 MainActivity 的生命週期有影響,並且跳轉主題爲 Dialog 的 Activity 與跳轉普通的 Activity 的生命週期變化相同。

5. 橫豎屏切換時生命週期變化

  MainActivity 在橫豎屏切換時生命週期的變化:
  
結論:橫豎屏切換時的生命週期調用爲:onPause() -> onStop() -> onDestory() -> onCreate() -> onStart() -> onResume() 。就是一個銷燬再重建的過程。

內存不足殺死 Activity 時的生命週期變化

  模擬內存不足殺死應用:先打開應用,然後按 home 鍵,使應用進入後臺,然後使用命令 adb shell am kill 包名將應用殺死。

  • 從打開應用到殺死應用的生命週期變化如下:

      在按 home 鍵之後,MainActivty 調用了 onPause() 與 onStop() 方法,並沒有調用 onDestory() 方法,所以主進程現在屬於後臺進程。
    結論:內存不足時,殺死應用,前臺的 Activity 生命週期爲 onPause() -> onStop() 。
  • 然後在點擊應用的圖標,打開應用,生命週期變化如下:

      可以看到 MainActivity 調用了 onCreate()、onStart() 和 onResume() 方法,Activity 重新創建了。

7. 異常情況下數據保存

  在 MainActivity 中覆蓋 onSaveInstanceState 和 onRestoreInstanceState 兩個方法。在 onSaveInstanceState 方法中保存 key 值爲 message ,值爲 onSaveInstanceState 的數值,在 onRestoreInstanceState 方法中獲取 key 值爲 message 對應的數值,使用橫豎屏切換來測試這兩個方法的調用,以及保存數值的獲取。

  • 從 MainActivity 開啓到切換橫豎屏的生命週期變化如下:

      橫豎屏切換時,MainActivity 調用了 onSaveInstanceState() 方法,切換之後 MainActivity 重新創建,並且調用了 onRestoreInstanceState() 方法,並從 Bundle 中取得了 onSaveInstanceState() 方法中保存的數據。

  • 再切換回來的生命週期變化如下:

      切換回來與切換的時候的生命週期變化一樣,先調用了 onSaveInstanceState() 方法,切換後 MainActivity 重新創建並調用 onRestoreInstanceState() 方法,並從 Bundle 中取得了 onSaveInstanceState() 方法中保存的數據。

  onCreate() 方法中也能獲取 onSaveInstanceState 方法中保存的數據,在 MainActivity 的 onCreate() 方法中增加獲取代碼。

  • 橫豎屏切換之後 onCreate() 打印的日誌如下:

      在 MainActivity 重新創建時,調用了 onCreate() 方法,並從 onCreate() 方法的 Bundle 中獲取到 onSaveInstanceState() 方法中存儲的值。注意:onCreate() 中從 Bundle 中獲取數據之前,一定要判空,因爲第一次進入的時候,Bundle 是空的,會有空指針異常。

8. 在異常情況下,系統默認恢復 EditText 的文本信息

  在 MainActivity 的佈局文件中添加 EditText,打開應用後,在輸入框內輸入一些文字。在橫豎屏切換後觀察輸入框內的文字是否和切換之前的文字相同。(通過橫豎屏切換觀察信息,注意 EditText 需要添加 id 才行)
  從打開應用,到橫豎屏切換之後輸入框的文字內容如下:

  在切換橫豎屏時,onPause() 方法中打印了 EditText 的文本內容,切換重建後,在 onResume() 中獲取到 EditText 的內容與之前的內容相同,並且要注意,重建後 onCreate() 與 onStart() 方法中獲取 EditText 的文本內容都是爲空。

9. 在異常情況下,系統默認恢復 TextView 的文本信息

  通過轉屏觀察信息,這裏只是通過 setText 方法動態設置文本內容,在這種情況下加了 id 也無法自動保存,這種情況可以通過給 TextView 設置 freezesText 屬性才能自動保存。
  打開應用後在點擊彈出標準的 AlertDialog 時修改 TextView 的內容,橫豎屏切換後,觀察 TextView 的內容是否和切換之前的文字相同。

  從打開應用,到橫豎屏切換之後 TextView 的文字內容如下:

  在切換橫豎屏時,onPause() 方法中打印了 TextView 的文本內容,切換重建後,在 onResume() 中獲取到 TextView 的內容與之前的內容相同,並且要注意,重建後 onCreate() 與 onStart() 方法中獲取 TextView 的文本內容是佈局文件中的默認內容。

10. 防止重建

  將 MainActivity 的 android:configChanges 設置爲 orientation ,在橫豎屏切換的時候防止重新被創建。

  • 橫豎屏切換時,生命週期的變化如下:

      可以看到在第一次進入 Activity 會調用 onCreate() -> onStart() -> onResume() 創建,之後切換橫豎屏並不會有任何的生命週期方法的調用。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章