Activity类中有关生命周期的方法有一下几种:
(1)onCreate(): 当活动第一次启动的时候会触发该方法,可以在此完成活动的初始化工作,该方法有一个参数,该参数可以是null,也可以是之前调用onSaveInstanceState()方法保存的状态信息;
(2)onStart(): 触发该方法表示所属的活动将会展示给用户;
(3)onResume(): 当一个活动和用户交互的时候将会触发该方法;
(4)onPause(): 当一个正在运行的活动因为其他的活动需要前台运行的Activity转入后台运行的时候会触发该方法,这时候需要将活动的状态持久化;
(5)onStop(): 当一个活动不需要展示给用户的时候会触发该方法,如果内存紧张的话,Linux系统为了给新的活动预留更多的存储空间会直接结束该活动,所以保存状态信息的操作应该在onPause里面进行,因为你无法保证你的onStop方法是否会执行;
(6)onRestart(): 当处于暂停状态的活动再次展现给用户的时候会调用该方法;
(7)onDestroy(): 当活动销毁时触发该方法,和onStop方法一样,如果内存紧张的话,也不会执行该方法;
(8)onSaveInstanceState(): 系统调用该方法,允许活动保存之前的状态,比如一串字符串的光标所处位置,通常情况下不需要覆写该方法,在默认的实现中已经提供了自动保存活动所涉及的用户界面组件的所有状态信息;
情况1
单个Activity 启动各种情况
//打开app
1.onCreate() → onStart() → onResume() → onPostResume()
//按返回键退出:
2.onPause() → onStop() → onDestroy()
// 2情况下 返回app,相当于重新打开app
3.onCreate() → onStart() → onResume() → onPostResume()
//按home 键退出 ,如果退出后清理后台,不会保证回调 onDestroy()
4.onPause() → onSaveInstanceState() → onStop()
//按任务菜单键:
5.onPause() → onSaveInstanceState() → onStop()
// 4.5 情况下重新返回app
6.onRestart() → onStart() → onResume() → onPostResume()
总结:如果直接退出的话就当前Activity 销毁,如果是按 home 键返回没有杀死app 情况下,先保存一下状态,防止Activity 意外结束( 如果Activity被回收了会调用 onRestoreInstanceState ) 然后再Stop 当前Activity
情况2
单个Activity 横屏和竖屏切换情况
//1.正常Activity 横竖屏切换
onPause() → onSaveInstanceState() → onStop() → onDestroy() →
onCreate() → onStart() → onRestoreInstanceState() → onResume() → onPostResume()
//2.配置activity
//orientation:消除横竖屏的影响 keyboardHidden:消除键盘的影响 screenSize:消除屏幕大小的影响
android:configChanges="orientation|screenSize"
android:configChanges="orientation|screenSize|keyboardHidden"
//如果Activity配置了上面的类型:
onConfigurationChanged()
总结:
(1)可以发现在设置了orientation|screenSize属性之后,在进行横竖屏切换的时候调用的方法是onConfigurationChanged,而不会重新加载Activity的各个生命周期;
(2)还有一点需要注意的是在进行横竖屏切换的时候在调用onStop之前会调用onSaveInstanceState来进行Activity的状态保存,随后在重新显示该Activity的onResume方法之前会调用onRestoreInstanceState来恢复之前由onSaveInstanceState保存的Activity信息;
情况3
单个Activity 锁屏情况:
//锁屏
onPause() → onSaveInstanceState() → onStop()
//解锁
onRestart() → onStart() → onResume() → onPostResume()
总结:相当于按 home 键退出或者按任务菜单键情况
情况4
两个 Activity 互相切换
//在第一个Activity 中跳转到第二个Activity
Activity1_onPause() →
Activity2_onCreate() → Activity2_onStart() → Activity2_onResume() → Activity2_onPostResume() →
Activity1_onSaveInstanceState() → Activity1_onStop()
//第二个Activity 按下返回键 ,在有 startActivityForResult 或 setResult 的情况下
//如果没有startActivity ,就不会回调 Activity1_onActivityResult()
Activity2_onPause()→
Activity1_onActivityResult() → Activity1_onRestart() → Activity1_onStart() → Activity1_onResume() → Activity1_onPostResume() →
Activity2_onStop() → Activity2_onDestroy()
总结:
(1)创建一个Activity的时候会首先执行onCreate方法,如果该Activity处于显示状态的话,会执行onStart方法,如果和用户发生交互的话,会执行onResume方法;
(2)当一个Activity从当前显示界面中消失之后并且这个Activity是Activity栈中的最后一个Activity的时候,会先后调用onPause、onStop、onDestroy方法来结束这个Activity并且有可能删除该Activity栈;
(3)当一个Activity从当前界面中消失但不是当前Activity栈中的最后一个Activity的话,他会先后调用onPause、onStop方法,但是不会调用onDestroy,如果下次从另一个Activity返回到该Activity的时候会直接执行onRestart、onStart来直接恢复该Activity就好,而不再需要重新调用onCreate;
情况5
Activity2 以弹框形式启动:在Activity2 XML 中添加 android:theme="@style/Theme.AppCompat.Dialog"
下面这种形式也可以实现只调用onPause 不调用 onStop
android:theme="@android:style/Theme.Translucent"
//1.通过 startActivity 启动弹出框 Activity2
Activity1_onPause()→
Activity2_onCreate() → Activity2_onStart() → Activity2_onResume() → Activity2_onPostResume() →
Activity1_onSaveInstanceState()
//finish Activity2 或者按返回键返回 Activity1
Activity2_onPause() →
Activity1_onResume() → Activity1_onPostResume() →
Activity2_onStop() → Activity2_onDestroy()
//2. 通过 new AlertDialog.Builder(Activity1.this).setTitle("测试").setPositiveButton("确定", null).show();
这种情况下 Activity1 生命周期没有任何变化
总结:
当通过startActivity
启动时可以看到当 Activity1 还处于可见状态时 不会调用 Activity1_onStop()
,其他和跳转 Activity 情况一致。
当通过AlertDialog
形式启动时 ,Activity1 没有任何生命周期变化 ,这也就是说AlertDialog应该是属于Activity的内部界面的。
onSaveInstanceState() 和 onRestoreInstanceState() 调用时机总结:
一、onSaveInstanceState(Bundle outState)在什么时机会被调用呢?
答案是当activity有可能被系统回收的情况下,而且是在onStop()之前。注意是有可能,如果是已经确定会被销毁,比如用户按下了返回键,或者调用了finish()方法销毁activity,则onSaveInstanceState不会被调用。
或者也可以说,此方法只有在activity被异常终止的情况下会被调用。
总结下,onSaveInstanceState(Bundle outState)会在以下情况被调用:
1、当用户按下HOME键时。
2、从最近应用中选择运行其他的程序时。
3、按下电源按键(关闭屏幕显示)时。
4、从当前activity启动一个新的activity时。
5、屏幕方向切换时(无论竖屏切横屏还是横屏切竖屏都会调用)。
补充:Android UI框架中几乎所有的UI控件都实现了onSaveInstanceState()方法,因此当activity被摧毁和重建时, 这些UI控件会自动保存和恢复状态数据,前提是你已经为这个控件指定过ID
二、onRestoreInstanceState什么时机被调用?
onRestoreInstanceState(Bundle savedInstanceState)只有在activity确实是被系统回收,重新创建activity的情况下才会被调用。
比如屏幕方向切换时,activity生命周期如下:
onPause -> onSaveInstanceState -> onStop -> onDestroy -> onCreate -> onStart -> onRestoreInstanceState -> onResume
在这里onRestoreInstanceState被调用,是因为屏幕切换时原来的activity确实被系统回收了
三、onCreate()里也有Bundle参数,可以用来恢复数据,它和onRestoreInstanceState有什么区别?
因为onSaveInstanceState 不一定会被调用,所以onCreate()里的Bundle参数可能为空,如果使用onCreate()来恢复数据,一定要做非空判断。
而onRestoreInstanceState的Bundle参数一定不会是空值,因为它只有在上次activity被回收了才会调用。
而且onRestoreInstanceState是在onStart()之后被调用的。有时候我们需要onCreate()中做的一些初始化完成之后再恢复数据,用onRestoreInstanceState会比较方便。
四、关于屏幕旋转保存数据的补充:
Object onRetainCustomNonConfigurationInstance()旋转时会调用此方法,在onStop()后调用,可以重写此方法返回一个对象(Fragment中无此方法)
Activity重建后可以在onCreate方法中通过getLastCustomNonConfigurationInstance()拿到上边保存的对象(Fragment中无此方法)
AndroidManifest.xml中设置android:configChanges=”orientation|screenSize”后,旋转屏幕将不会重新调用各个生命周期,当然也不会调用保存数据的方法,只会调用onConfigurationChanged(Configuration newConfig)方法