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 方法来存储和恢复数据。如果一个进程中没有四大组件在执行,那么这个进程很快就会被系统杀死。