Android 進階1:Activity 的生命週期
典型情況下的生命週期
7個生命週期
onCreate :Activity 正在被建立
- 初始化佈局和資料
onRestart :Activity 正在重新啟動,從不可見變為可見狀態
- 從 Home 或者新 Activity 返回舊 Activity
onStart :Activity 正在被啟動,已經顯示出來,但是沒有出現在前臺
- 無法和使用者互動
onResume :Activity 已經可見了,顯示到前臺
- 可以互動
onPause :Activity 正在被停止
- 可以做儲存資料、停止動畫等操作
- 但不能做耗時操作,因為 onPause 執行完才會執行新 Activity 的 onResume
onStop :Activity 即將停止
- 可以做稍微重量級的回收
- 但同樣不能太耗時 ?why
onDestroy :Activity 即將被銷燬
- 回收和最終的資源釋放
一些特殊情況
1.A 中啟動 B,如果 B 是透明主題,A 的 onStop 不會被呼叫 ???
2.從 B 中返回 A,A 的生命週期:onRestart -> onStart -> onResume
3.onStart 和 onStop 在該 Activity 是否在可見時回撥;
而 onResume 和 onPause 則在 Activity 是否在前臺時回撥。
注:
“可見”只是說顯示,但不一定是使用者可以看到、互動;
“前臺”就是看得見、摸得著。
4.如何實現點選返回鍵,Activity 的 onDestroy 不被執行?
在所在的 Activity 中重寫 onKeyDown() 方法,攔截返回事件,然後呼叫 moveTaskToBack() 方法:
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK){ moveTaskToBack(true);//將當前 Activity 的 Task 放到 Activity 棧的後邊 return false; } return super.onKeyDown(keyCode, event); }
5.Activity 的啟動流程簡述:
- Instrumentation 處理啟動 Activity 的請求,然後通過 Binder 將請求發給 AMS
- AMS 維護著一個 ActivityStack 並負責棧中 Activity 的狀態管理
- AMS 通過 ActivityThread 去同步 Activity 的狀態,從而完成生命週期的呼叫
Activity 的 Task 和 棧的概念?
異常情況下的生命週期
系統回收或者當前裝置 Configuration 改變導致 Activity 被銷燬重建的情況。
異常狀態儲存/恢復方法
在系統配置發生改變時,預設情況下 Activity 會被銷燬重建。
異常終止的情況下會呼叫 onSaveInstanceState() 方法,重新建立後會呼叫 onRestoreInstanceState():
- 狀態儲存呼叫順序:onPause -> onSaveInstanceState -> onStop
- 狀態恢復呼叫順序:onStart -> onRestoreInstanceState - >onResume
- 資料通過鍵值對的形式儲存到 Bundle 中
資料恢復在 onCreate 或者 onRestoreInstanceState 中進行都可以,但是官方檔案建議在
onRestoreInstanceState 中,因為它被呼叫時 bundle 一定是有值的,不需要判斷。
系統自動做的儲存/恢復工作
在 Activity 的異常情況下,系統會這兩個儲存、恢復方法中為我們做一定的工作,比如儲存當前 Activity 的檢視結構(View 的狀態)。
Activity 異常終止時,系統儲存 View 狀態的流程簡述:
- Activity 呼叫 onSaveInstanceState 儲存資料
- 然後 Activity 委託 Window 儲存資料
- Window 再委託上面的頂級容器儲存資料
頂級容器(一般來說是 DecorView)再一一通知它的子元素儲存資料
委託思想:上層委託下層去處理一件事。
比如這裡的資料恢復,還有 View 的繪製過程、事件分發等。
系統記憶體不足時,優先殺死低優先順序的 Activity
Activity 的三種優先順序,從高到低順序:
前臺 Activity
- 正在和使用者互動
- 優先順序最高,最不可能被回收
可見但非前臺
- 比如彈出 Dialog 的 Activity
後臺 Activity
- 已經暫停,執行了 onStop
- 優先順序最低
四大元件的優先順序都比較高,因此後臺想執行耗時工作時,需要依賴四大元件來保活。
比如講後臺工作放到 Service 中。
指定在某些配置改變時 Activity 不重建
我們可以在 AndroidManifest.xml 中配置 android:configChanges 來指定該 Activity 在哪些系統配置改變時不重新建立。
配置項很多,常用的是這四個:
android:configChanges="screenSize|orientation|keyboardHidden|locale"
- screenSize|orientation 指的是在螢幕旋轉和尺寸改變時不重新建立
- keyboardHidden 指的是可用鍵盤的改變
- locale 指的是系統語言切換
注意:
從 Android 3.2(API 級別 13)開始,當裝置在縱向和橫向之間切換時,“螢幕尺寸”也會發生變化。
因此,在開發針對 API 級別 13 或更高版本(正如 minSdkVersion 和 targetSdkVersion
屬性中所宣告)的應用時,若要避免由於裝置方向改變而導致執行時重啟,則除了 “orientation” 值以外,您還必須新增
“screenSize” 值。
現在,當其中一個配置發生變化時,Activity 不會重啟。相反,Activity 會呼叫 onConfigurationChanged()方法,並且向此方法傳遞 Configuration 物件,這個物件代表當前所有配置,你可以根據不同配置進行不同的處理:
@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // Checks the orientation of the screen if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show(); } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){ Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show(); } }
如果在配置改變時仍使用舊的狀態,則可以不實現 onConfigurationChanged()。
喜歡的話請幫忙轉發一下能讓更多有需要的人看到吧,有些技術上的問題大家可以多探討一下。

image

image