目录
1. Activity的各种生命周期
2. onSaveInstanceState() 与 onRestoreInstanceState()
3. Activity生命周期的变化
4. 总结
1. Activity的各种生命周期
系统中的Activity由Activity堆栈管理,当启动一个新的Activity的时候,这个Activity被放置在栈顶,并处于正在运行状态。前一个Activity在堆栈中位于新的Activity下面,并且在新的Activity退出前不会出现在前台。
下面用一张图展示Activity完整生命周期:
- onCreate
在Activity第一次被创建时调用onCreate方法。我们通常在onCreate方法中加载布局,初始化控件。 - onStart
在Activity变为可视的时候,调用onStart方法。 - onResume
当Activity处于栈顶,并处于正在运行状态,可以与用户进行交互的时候,调用onResume方法。 - onPause
当Activity已经失去焦点,且依旧是可视状态时调用onPause方法,此时Activity无法与用户进行交互。 - onStop
当Activity从可视变为不可视的时候,调用onStop方法。 - onDestory
onDestory方法在Activity被销毁前调用。 - onRestart
onRestart方法在Activity被重新启动时调用,在Activity第一次被创建的时候不会调用。
完整生命周期:
完整生命周期在Activity第一次创建调用onCreate方法到销毁前调用onDestroy方法之间。
可视生命周期:
可视生命周期在Activity调用onStart方法变为可视到调用onStop方法变为不可视之间。
前台生命周期:
前台生命周期在Activity调用onResume方法变得可与用户交互到调用onPause方法变得不可与用户交互之间。
2. onSaveInstanceState() 与 onRestoreInstanceState()
系统在“未经你许可”销毁Activity时调用onSaveInstanceState方法,用于保存Activity状态信息。onRestoreInstanceState方法在Activity被系统销毁之后恢复Activity时被调用,用于恢复Activity状态信息。可重写这两个方法在系统“未经你许可”销毁Activity时保存和恢复你的数据。
所谓“未经你许可”指的是非人为销毁Activity,例如按下回退键退出页面属于人为,系统因内存不足回收销毁Activity属于非人为。
-
什么时候调用onSaveInstanceState方法
(1)、当用户按下HOME键时。
(2)、切换到其他进程时。
(3)、锁屏时。
(4)、启动新的Activity时。
(5)、屏幕方向切换时。 -
什么时候调用onRestoreInstanceState方法
在Activity被系统销毁,又回到该Activity的时候。如用户按下HOME键又马上返回该Activity,这个时候该Activity一般不会因为内存不足而被系统回收,故不调用onRestoreInstanceState方法。所以onSaveInstanceState与onRestoreInstanceState不一定会成对被调用。
3. Activity生命周期的变化
分别新建3个Activity,MainActivity、TestActivity、TransparentActivity,并在每个Activity中重写onCreate,onStart,onResume,onPause,onStop,onDestroy,onRestart,onSaveInstanceState,onRestoreInstanceState这9个方法,如下所示:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.act_main)
Log.e("MainActivity", "onCreate")
}
override fun onStart() {
super.onStart()
Log.e("MainActivity", "onStart")
}
override fun onResume() {
super.onResume()
Log.e("MainActivity", "onResume")
}
override fun onPause() {
super.onPause()
Log.e("MainActivity", "onPause")
}
override fun onStop() {
super.onStop()
Log.e("MainActivity", "onStop")
}
override fun onDestroy() {
super.onDestroy()
Log.e("MainActivity", "onDestroy")
}
override fun onRestart() {
super.onRestart()
Log.e("MainActivity", "onRestart")
}
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
super.onRestoreInstanceState(savedInstanceState)
Log.e("MainActivity", "onRestoreInstanceState")
}
override fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState)
Log.e("MainActivity", "onSaveInstanceState")
}
}
代码准备好了,来观察下面各种请看下Activity生命周期的变化:
- 启动Activity并点击回退键退出Activity
启动Activity,首先创建Activity,然后页面变得可见,最后页面准备好与用户交互,所以生命周期的调用顺序应该是 onCreate() -> onStart() -> onResume(),如下图所示:
点击回退键退出Activity,首先停止与用户交互,然后页面变得不可见,最后销毁Activity,所以生命周期的调用顺序应该是 onPause() -> onStop() -> onDestory(),如下图所示:
- 按下HOME键并再次点击应用
按下HOME键后,首先页面停止所有交互,然后页面变得不可见,最后回到桌面。这时候页面并没有被销毁,只是转入后台,但是也存在被系统回收的风险,所以系统会在onPause和onStop之间调用onSaveInstanceState方法保存Activity状态信息,所以生命周期的调用顺序应该是 onPause() -> onSaveInstanceState() -> onStop(),如下图所示:
再次点击应用,如果应用没有被系统回收,只是从后台调回前台,那么首先是重新打开页面,然后页面变得可见,最后页面变得可以与用户交互,所以生命周期的调用顺序应该是 onRestart() -> onStart() -> onResume(),如下图所示:
- 切换到其他应用并切回来
当我们切换到其他应用的时候,页面首先是停止与用户交互,然后页面变得不可见,然后进入到别的应用中,由于页面存在被系统回收的风险,所以系统会在onPause和onStop之间调用onSaveInstanceState方法保存Activity状态信息,所以生命周期的调用顺序应该是 onPause() -> onSaveInstanceState() -> onStop(),如下图所示:
切回来的时候,如果应用没有被系统回收,首先是重新打开页面,然后页面变得可见,最后页面变得可以与用户交互,所以生命周期的调用顺序应该是 onRestart() -> onStart() -> onResume(),如下图所示:
- 锁屏并解锁
锁屏的时候,页面首先是停止与用户交互,然后页面变得不可见,然后锁屏,由于页面存在被系统回收的风险,所以系统会在onPause和onStop之间调用onSaveInstanceState方法保存Activity状态信息,所以生命周期的调用顺序应该是 onPause() -> onSaveInstanceState() -> onStop(),如下图所示:
解锁的时候,如果应用没有被系统回收,首先是重新打开页面,然后页面变得可见,最后页面变得可以与用户交互,所以生命周期的调用顺序应该是 onRestart() -> onStart() -> onResume(),如下图所示:
- 跳转到另一个非透明Activity并点击回退键返回
从MainActivity跳转到TestActivity,首先停止MainActivity的交互,然后创建TestActivity,然后TestActivity变得可见,然后TestActivity变得可以与用户交互,最后MainActivity变得不可见,由于MainActivity存在被系统回收的风险(可能性不大),所以系统会调用onSaveInstanceState方法保存MainActivity状态信息。生命周期的调用顺序如下图所示:
点击回退键返回MainActivity,首先停止TestActivity的交互,然后重新打开MainActivity,然后MainActivity变得可见,然后MainActivity变得可以与用户交互,然后TestActivity变得不可见,最后TestActivity被销毁。生命周期的调用顺序如下图所示:
- 跳转到另一个透明Activity并点击回退键返回
在styles中创建一个透明的主题:
<style name="AppTransparentTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="windowNoTitle">true</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
</style>
TransparentActivity在AndroidManifest中声明透明主题
<activity android:name=".TransparentActivity"
android:theme="@style/AppTransparentTheme"/>
从MainActivity跳转到透明的Activity,也就是TransparentActivity。由于TransparentActivity是一个透明的Activity,所以他的底层MainActivity还是可视的,所以MainActivity的onStop方法没有被调用,只调用了onPause方法。生命周期的调用如下图所示:
点击返回键,回到MainActivity。因为MainActivity跳转到TransparentActivity时并没有变为不可视,所以没有调用onStop,回到MainActivity之后,也不需要重新启动MainActivity,所以只需要恢复交互就可以了。生命周期的调用如下图所示:
- 由竖屏转为横屏
旋转屏幕后,系统会销毁然后启动该Activity,首先停止Activity的交互,然后Activity变得不可见,然后销毁Activity,销毁过后启动Activity,然后Activity变得可见且屏幕旋转,最后旋转屏幕过后的Activity变得可以交互。由于旋转屏幕属于“未经你许可”销毁Activity,所以同步执行onSaveInstanceState和onRestoreInstanceState这两个方法来保存和恢复Activity的状态。生命周期的调用顺序如下图所示:
4. 总结
Activity是Android四大组件之一,也是与用户交互最频繁的组件。本篇文章主要总结了Activity的各种生命周期和这些生命周期在不同情况下的变化。