一.Activity的生命周期
从图中我们可以看出,Activity的主要生命周期有:onCreate()、OnStart()、OnRestart()、OnResume()、OnPause()、OnStop()、OnDestroy() 这7个方法。
二. 项目工程说明
采用语音:Kotlin(基于1.2.61)
测试机:魅族 M15(基于Android 7.1.2)
项目名称:activity_basic_use
编译版本:
minSdkVersion 17
targetSdkVersion 26
三.生命周期方法的调用
先新建4个文件,MainActivity、SecondActivity、ThirdActivity、FourthActivity,其中MainActivity用来做跳转测试的主Activity,SecondActivity是普通的Activity,ThirdActivity是以Dialog形式显示的Activity,FourthActivity使用透明主题的普通Activity,并新建4个布局文件,布局文件很简单,不再贴出布局文件中的代码,然后覆写相关的生命周期的方法,下面是MainActivity代码:
class MainActivity : Activity() {
private var button1:Button? = null
private var button2:Button? = null
private var button3:Button? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button1 = findViewById(R.id.button1)
button2 = findViewById(R.id.button2)
button3 = findViewById(R.id.button3)
button1?.setOnClickListener {
val intent = Intent(this,SecondActivity::class.java)
startActivity(intent)
}
button2?.setOnClickListener {
val intent = Intent(this,ThirdActivity::class.java)
startActivity(intent)
}
button3?.setOnClickListener {
val intent = Intent(this,FourthActivity::class.java)
startActivity(intent)
}
println("MainActivity->onCreate")
}
override fun onStart() {
super.onStart()
println("MainActivity->onStart")
}
override fun onRestart() {
super.onRestart()
println("MainActivity->onRestart")
}
override fun onResume() {
super.onResume()
println("MainActivity->onResume")
}
override fun onPause() {
super.onPause()
println("MainActivity->onPause")
}
override fun onStop() {
super.onStop()
println("MainActivity->onStop")
}
override fun onDestroy() {
super.onDestroy()
println("MainActivity->onDestroy")
}
}
然后是SecondActivity里面的代码:
class SecondActivity : Activity() {
private var button2: Button? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
button2 = findViewById(R.id.button2)
button2?.setOnClickListener{
finish()
}
println("SecondActivity->onCreate")
}
override fun onStart() {
super.onStart()
println("SecondActivity->onStart")
}
override fun onRestart() {
super.onRestart()
println("SecondActivity->onRestart")
}
override fun onResume() {
super.onResume()
println("SecondActivity->onResume")
}
override fun onPause() {
super.onPause()
println("SecondActivity->onPause")
}
override fun onStop() {
super.onStop()
println("SecondActivity->onStop")
}
override fun onDestroy() {
super.onDestroy()
println("SecondActivity->onDestroy")
}
}
- 首次运行程序,得到以下输出:
- 按下
Home键后,再次点击应用图标后,得到以下输出: - 按下
返回键后,得到以下输出: - 重新运行程序,点击
button1按钮后,跳转到SecondActivity,得到以下输出: - 点击
SecondActivity中的按钮后,得到以下输出: - 重新运行程序,点击
button2按钮后,弹出Dialog形式的ThirdActivity,得到以下输出: - 点击
ThirdActivity中的按钮后,得到以下输出: - 重新运行程序,点击
button3按钮后,显示透明主题的Activity,得到以下输出: - 点击
FourthActivity中的按钮后,得到以下输出:
四.生命周期方法说明(《Android开发艺术探索》)
onCreate()
这是生命周期的第一个方法,表示Activity正在创建,在这个方法中,我们可以做一些初始化操作,比如加载布局资源、初始化Activity相关数据等。
onStart()
表示Activity正在被启动即将开始,这时Activity已经可见了,只不过还没有出现在前台,无法和用户进行交互。可以理解为Activity已经显示出来了,但是用户看不到。
onRestart()
表示Activity正在重新启动,一般情况下,当Activity从不可见状态重新变为可见状态后,此方法就会被回调,这种情形一般都是用户行为所导致的,比如用户按下Home键后或者打开了一个新的Activity,接着又回到了这个Activity,就会出现这种情况。
onResume()
表示Activity已经可见了,并且出现在前台开始活动,可以和用户进行交互。需要注意onStart和onResume的对比,二者都表示Activity可见,但是onStart表示Activity在后台并且无法和用户进行交互,而onResume表示Activity已经显示在前台,可以和用户进行交互。
onPause()
表示Activity正在被停止,此时可以做一些数据存储、动画停止等,但不能是耗时的操作。一般情况下会接着回调onStop方法,如果此时再次回到这个Activity后,会接着回调onResume方法。但也有特殊情况,比如显示一个以Activity形式的Dialog或者采用了透明主题就不会回调onStop方法。
onStop()
表示Activity正在被停止,此时Activity变得不可见,在这个方法中可以做一些稍微重量级的回收工作,但也不能太耗时。
onDestroy()
表示Activity正在被销毁,这是Activity生命周期的最后一个方法,在这个方法中,我们可以做回收工作和一些资源的释放。
总结
从整个生命周期来说,onCreate()和onDestroy()是配对的,表示Activity的创建和销毁,并且只能回调一次;onStart()和onStop()是配对的,这是从Activity是否可见来说的,随着用户的操作和屏幕的点亮或者熄灭,这2个方法会回调多次;onResume()和onPause()是配对的,这是从Activity是否在前台来说的,随着用户的操作和屏幕的点亮或者熄灭,这2个方法会回调多次。onStart()+onStop()和onResume()+onPause(),这两组回调方法表示的意义不同,onStart()+onStop()是从Activity是否可见这个角度来回调的,onResume()+onPause()是从Activity是否位于前台这个角度来回调的,除了这种区别,在实际使用中并没有其他明显区别。
五.其他情况生命周期回调
锁屏
Activity没有被系统回收,就是普通的切换到不可见状态;如果被系统回收后,会销毁当前Activity,然后重新创建一个。
旋转屏幕(程序运行时,默认都是竖屏)
- 未在
Manifest中进行设置,竖屏切到横屏(横屏再切回到竖屏,输出是和下面一样的,也就是说会回调2次): 可以看出旋转屏幕后,Activity被销毁,然后重新创建,此时就算重写了onConfigurationChanged方法,也不会调用此方法 - 在
Manifest中设置MainActivity的configChanges="orientation|screenSize",并重写onConfigurationChanged方法,会得到以下输出:
- 竖屏切到横屏:
可以看到,Activity并没有销毁,而是回调了onConfigurationChanged方法 - 横屏切回到竖屏:
可以看到,Activity也没有被销毁,也是回调了onConfigurationChanged方法
故从以上可以知道,配置configChanges="orientation|screenSize"可以阻止Activity的销毁与重新创建,如果少了其中的任何一个,都会导致Activity的销毁。
- configChanges常用属性值的相关说明:
| 属性值 | 说明 |
|---|---|
| locale | 用户所在区域发生变化,一般是用户切换了语言 |
| keyboardHidden | 键盘的可用性发生了改变,比如调出或隐藏了键盘 |
| fontScale | 字体比例发生了变化 |
| orientation | 屏幕方向发生了变化 |
| screenSize | 屏幕尺寸发生了变化 |
更多的属性值,直接截取《Android开发艺术探索》中的图:
保存数据
屏幕方向发生了旋转,或者Activity由于资源内存不足被系统杀死等异常销毁,并且有机会重新显示,系统会回调两个方法:onSaveInstanceState(outState:Bundle?)和onRestoreInstanceState(savedInstanceState:Bundle?)。如果在EditText或者其他控件中有值的话,可以在onSaveInstanceState方法中,调用Bundle对象的相关putXxx方法进行存储,然后在onRestoreInstanceState方法或者onCreate中调用Bundle的getXxx方法进行获取对应的值,一般我们推荐在onCreate中进行获取。注意:在正常的生命周期中并不会回调这两个方法
项目地址: github.com/leewell5717…
六. 总结
本文对Activity生命周期的基础做了一些讲述,生命周期对于我们来说是非常重要的,也有许多面试官喜欢问关于生命周期的基础,可能本文总结的不是很全面,或者有错误的地方,欢迎指出,也欢迎给我一些建议,我将在后面的写作中提升自己。