1.生命週期
生命週期如下如圖所示:
1.1 典型生命週期分析:
在正常情況下,生命週期爲如下經歷:
-
onCreate():Activity正在被創建,在這個方法中可以做一些初始化工作,比如調用setContentView去加載佈局資源、初始化Activity所需要的資源等。
-
onRestart():Activity正在重新啓動,一般情況下,在當前activity由不可見變爲可見的時候調用該方法。這種情況一般由用戶行爲所致。
-
onStart():activity正在被啓動,即將開始,這時候activity可見但不在前臺,用戶無法操作。可以理解爲activity已經顯示了但是我們還看不到。
-
onResume() : 此時activity已經可見,並且可以交互。和onStart()方法的區別在於onStart()時activity還在後臺,不能交互。
-
onPause(): activity正在停止,正常情況下onStop會被接着調用。如果在這個時候快速返回當前activity則會直接調用onResume()。但是這種情況一般很難實現。
-
onStop(): activity即將停止,可以做一些重量級的回收工作但是不能做耗時操作。
-
onDestriy(): activity即將被銷燬。
具體實例如下:(使用kotlin實現)
class MainActivity : AppCompatActivity() {
val TAG : String = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
LogUtils.d("onCreate")
}
override fun onPause() {
super.onPause()
LogUtils.d("onPause")
}
override fun onDestroy() {
super.onDestroy()
LogUtils.d("onDestroy")
}
override fun onStart() {
super.onStart()
LogUtils.d("onStart")
}
override fun onResume() {
super.onResume()
LogUtils.d("onResume")
}
override fun onStop() {
super.onStop()
LogUtils.d("onCreate")
}
override fun onRestart() {
super.onRestart()
LogUtils.d("onRestart")
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
LogUtils.d("onNewIntent")
}
}
1.1.1 正常情況下生命週期方法回調情況如下:
- 一般情況下啓動新的activity的生命週期方法執行順序爲:
onCreate() -> onStart() -> onRessume()
- 當用戶打開新的activity或切換到桌面的時候,回調順序爲:
onPause() -> onStop()
此時存在特殊情況:當啓動的activity主題爲透明,則當前activity不會回調onStop()方法。
- 當用戶再次回到原Activity時。,回調如下:
onRestart() -> onStart() -> onResume()
- 當用戶按返回鍵回退時,回調如下:
onPause() -> onStop() -> onDestroy()
1.1.1.1 啓動新的activity時的生命週期
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
LogUtils.d("onCreate")
// 跳轉到第二個頁面
btn2activity.setOnClickListener {
var sIntent = Intent()
sIntent.setClass(MainActivity@this,SecondActivity::class.java)
startActivity(sIntent)
}
}
第二個頁面:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
LogUtils.d("onCreate")
}
override fun onPause() {
super.onPause()
LogUtils.d("onPause")
}
override fun onDestroy() {
super.onDestroy()
LogUtils.d("onDestroy")
}
override fun onStart() {
super.onStart()
LogUtils.d("onStart")
}
override fun onResume() {
super.onResume()
LogUtils.d("onResume")
}
override fun onStop() {
super.onStop()
LogUtils.d("onCreate")
}
override fun onRestart() {
super.onRestart()
LogUtils.d("onRestart")
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
LogUtils.d("onNewIntent")
}
生命週期日誌爲:
2019-02-16 15:08:23.340 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.340 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onPause(MainActivity.kt:26)
2019-02-16 15:08:23.340 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 15:08:23.340 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onPause
2019-02-16 15:08:23.340 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.429 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.430 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ SecondActivity.onCreate(SecondActivity.kt:15)
2019-02-16 15:08:23.430 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 15:08:23.430 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onCreate
2019-02-16 15:08:23.430 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.431 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.431 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ SecondActivity.onStart(SecondActivity.kt:31)
2019-02-16 15:08:23.431 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 15:08:23.432 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onStart
2019-02-16 15:08:23.432 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.435 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.435 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ SecondActivity.onResume(SecondActivity.kt:37)
2019-02-16 15:08:23.435 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 15:08:23.435 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onResume
2019-02-16 15:08:23.435 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.803 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.805 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onStop(MainActivity.kt:50)
2019-02-16 15:08:23.805 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 15:08:23.805 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onStop
2019-02-16 15:08:23.805 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
1.1.2 異常情況下生命週期分析
1. 資源相關的系統配置發生改變導致Activity被殺死並重啓
當系統配置發生變化後(例如默認情況下的橫豎屏切換),activity會被銷燬,onPause、onStop、onDestroy方法均會被調用,同時,activity是在異常情況下被銷燬,所以還會調用activity的onSaveInstanceState方法,保存當前activity的狀態。這個方法調用是在onStop之前,它和onPause沒有順序關係。這個方法的調用只是在異常情況下,正常情況下不會調用。當activity被重新創建之後,系統會調用onRestroeInstanceState方法,並且將activity銷燬時onSaveInstanceState方法保存的Bundle對象最爲參數同時傳遞給onRestroeInstanceState和onCreate方法。因此我們可以通過onRestroeInstanceState和onCreate方法來判斷activity是否被重建,如果被重建,則使用bundle對象的參數恢復。
示例如下:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
LogUtils.d("onCreate")
if (savedInstanceState != null) {
val string = savedInstanceState!!.getString("extra_test")
LogUtils.d("[onCreate] restroe extra_test == " + string)
}
}
override fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState)
LogUtils.d("onSaveInstanceState")
outState?.putString("extra_test","test")
}
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
super.onRestoreInstanceState(savedInstanceState)
val string = savedInstanceState!!.getString("extra_test")
LogUtils.d("[onRestoreInstanceState] restroe extra_test == " + string)
}
橫豎屏切換時的生命週期調用如下:
2019-02-16 16:33:46.975 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.975 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onPause(MainActivity.kt:31)
2019-02-16 16:33:46.975 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:46.975 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onPause
2019-02-16 16:33:46.975 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.976 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.977 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onSaveInstanceState(MainActivity.kt:73)
2019-02-16 16:33:46.977 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:46.977 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onSaveInstanceState
2019-02-16 16:33:46.977 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.978 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.979 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onStop(MainActivity.kt:55)
2019-02-16 16:33:46.979 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:46.979 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onStop
2019-02-16 16:33:46.979 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.979 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.980 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onDestroy(MainActivity.kt:37)
2019-02-16 16:33:46.980 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:46.980 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onDestroy
2019-02-16 16:33:46.980 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.055 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onCreate(MainActivity.kt:17)
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onCreate
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onCreate(MainActivity.kt:20)
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ [onCreate] restroe extra_test == test
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.057 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.058 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onStart(MainActivity.kt:43)
2019-02-16 16:33:47.058 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:47.058 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onStart
2019-02-16 16:33:47.058 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.058 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.059 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onRestoreInstanceState(MainActivity.kt:80)
2019-02-16 16:33:47.059 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:47.059 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ [onRestoreInstanceState] restroe extra_test == test
2019-02-16 16:33:47.059 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.059 3025-3025/com.xyd.activitylaunchmodedemo D/ActivityThread: add activity client record, r= ActivityRecord{76602aa token=android.os.BinderProxy@30b5a73 {com.xyd.activitylaunchmodedemo/com.xyd.activitylaunchmodedemo.MainActivity}} token= android.os.BinderProxy@30b5a73
2019-02-16 16:33:47.061 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.061 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onResume(MainActivity.kt:49)
2019-02-16 16:33:47.061 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:47.061 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onResume
2019-02-16 16:33:47.061 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
從日誌文件可以看出:在切換時,先調用onSaveInstanceState()方法,保存數據,然後切換之後調用onCreate和onRestoreInstanceState方法,獲取保存的數據。
2. 資源內存不足導致優先級低的activity被殺死
首先先分清activity的優先級,如下三種:
- 前臺activity —正在和用戶交互,優先級最高
- 可見但非前臺activity— 比如activity中彈出了一個dialog對話框,導致activity可見但是位於後臺,無法和用戶交互。
- 後臺activity — 已經被暫停的activity,比如A啓動B之後,A的優先級低,B的優先級最高
當系統內存不足時,系統會按照上邊的優先級,有低到高的優先級殺死目標activity所在的進程,並在後續通過onSaveInstanceState和onRestoreInstanceState 方法來存儲和恢復數據。如果一個進程中沒有四大組件在執行,那麼這個進程很快就會被系統殺死。