# Activity
# Activity生命周期
- 启动Activity:
onCreate()⟶onStart()⟶onResume(),进入运行状态; - Activity退居后台(Home或者启动了新的Activity):
onPause()⟶onStop(); - Activity返回前台:
onRestart()⟶onStart()⟶onResume(); - 如果Acitivity后台期间内存不足,再次启动时就会重新执行启动流程;
- 锁屏:
onPause()⟶onStop(); - 解锁:
onStart()⟶onResume();
具体方法介绍:
onCreate():在每个Activity中都会重写这个方法,它会在活动第一次被创建的时候调用;onStart():这个方法由不可见变为可见时调用;onResume():这个方法在Activity准备好和用户进行交互时调用。此时的活动肯定位于活动返回栈的栈顶,并且处于运行状态;onPause():这个方法是当系统准备启动或者恢复另一个活动的时候调用。通常会在这个方法里释放一些非常消耗CPU的资源等;onStop():这个方法在完全不可见的时候调用;onDestroy():这个方法在活动被销毁之前调用,之后活动的状态将变为销毁状态;onRestart():这个方法在活动由停止状态变为运行状态之前调用,即活动被重新启动了

三个时期:
- 完整生存期:活动在
onCreate()到onDestroy()方法之间所经历的就是完整生存期。一般情况下,一个活动会在onCreate()方法中完成各种初始化操作,而在onDestroy()方法中完成释放内存的操作; - 可见生存期:活动在
onStart()到onStop()方法之间所经历的就是可见生存期。可见生存期的的意思就是活动对于用户总是可见的(即使有可能与用户无法交互); - 前台生存期:活动在
onResume()和onPause()方法之间的就是时期就是前台生存期。在前台生存期内,活动总是处于运行状态的,即此时的活动是可以和用户进行交互的。
# 横竖屏切换时Activity的生命周期变化
这需要判断AndroidManifest.xml中是否设置了configChanges属性。而configChanges常用的属性有:
orientation:屏幕在纵向和横向间旋转keyboardHidden:键盘显示或者隐藏screenSize:屏幕大小改变了
# ① 如果AndroidManifest没有设置configChanges属性
如果是从竖屏启动切换横屏:
竖屏启动:
onCreate()⟶onStart()⟶onResume()切换横屏:
onPause()⟶onSavedInstanceState()⟶onStop()⟶onDestroy()⟶onCreate()⟶onStart()⟶onRestoreInstanceState()⟶onResume()⟶onPause()⟶onStop()⟶onDestroy()(Android6.0、7.0、8.0适用)如果是从横屏启动切换竖屏:
生命周期与从竖屏启动切换横屏一样。
总结:如果没有设置configChanges属性的话,在Android6.0、7.0、8.0的手机上表现是一样的。首先是正常地走一遍流程(在onPause()之后会有onSavedInstanceState()),然后重新创建之后在onStart()之后会有onRestoreInstanceState()。
# ② 如果AndroidManifest设置了android:configChanges="orientation"
如果是从竖屏启动切换横屏:
Android 6.0 竖屏启动:
onCreate()⟶onStart()⟶onResume()切换横屏:onPause()⟶onSavedInstanceState()⟶onStop()⟶onDestroy()⟶onCreate()⟶onStart()⟶onRestoreInstanceState()⟶onResume()⟶onPause()⟶onStop()⟶onDestory()Android 7.0 竖屏启动:
onCreate()⟶onStart()⟶onResume()切换横屏:onConfigurationChanged()⟶onPause()⟶onSavedInstanceState()⟶onStop()⟶onDestroy()⟶onCreate()⟶onStart()⟶onRestoreInstanceState()⟶onResume()⟶onPause()⟶onStop()⟶onDestroy()Android 8.0 竖屏启动:
onCreate()⟶onStart()⟶onResume()切换横屏:onConfigurationChanged()
总结:在设置了configChanges属性为orientation之后,Android 6.0的生命周期与没有设置是一样的。而Android 7.0则会先多回调一个onConfigurationChanged()方法,剩下的流程一样。Android 8.0则只是回调了onConfigurationChanged()方法,并没有走Activity生命周期的方法。
如果是从横屏启动切换竖屏:
生命周期与从竖屏启动切换横屏一样。
# ③ AndroidManifest设置了android:configChanges="orientation|keyboardHidden|screenSize"
竖屏启动:onCreate()⟶onStart()⟶onResume()切换横屏:onConfigurationChanged()(Android6.0、7.0、8.0适用)
总结:当设置了android:configChanges="orientation|keyboardHidden|screenSize时,就不会调用Activity其它生命周期的方法,只会调用onConfigurationChanged()方法。
# ④ AndroidManifest设置了android:configChanges="orientation|screenSize"
与orientation|keyboardHidden|screenSize相同,只回调onConfigurationChanged()方法。
# ⑤ AndroidManifest设置了android:configChanges="orientation|keyboardHidden"
与只设置了orientation的相同,Android 6.0、7.0会回调生命周期的方法,Android 8.0则只回调onConfigurationChanged()方法。
总结(不同手机系统系统可能会有略微差异)
- 不设置
configChanges属性是不会回调onConfigurationChanged()方法的,且切屏的时候会回调生命周期的方法; - 只有设置了
orientation和screenSize才会保证不会调用生命周期的方法,且切屏的时候只会回调onConfigurationChanged()方法; - 如果设置了
orientation而没有设置screenSize,那么切屏就会调用onConfigurationChanged()方法,但仍然会走生命周期;
# Activity A启动了Activity B,它们的生命周期的变化
启动Activity A
onCreate()创建活动A,onStart()显示在屏幕上,onResume()处于运行状态;在Activity A中启动Activity B
活动A被暂停,使用
onPause()进入暂停状态;onCreate()创建活动B,onStart()显示活动B在屏幕上,onResume()让活动B进入运行状态;活动A经过onStop()进入停止状态;从Activity B中返回Activity A(比如按物理返回键)
活动B用
onPause()方法进入暂停状态;活动A被重启,使用onRestart()方法从停止状态进入活动状态,调用onStart()方法使活动A显示在屏幕上,onResume()方法进入运行状态;活动B被onStop()方法进入停止状态,最后使用onDestroy()方法销毁;继续按物理返回键
活动A用
onPause()方法暂停,然后用onStop()方法停止,最后用onDestroy()方法被销毁;
# onSaveInstanceState()和onRestoreInstanceState()调用的过程和时机
- 调用时机:Activity的异常情况下(例如转动屏幕或者被系统回收)的情况下,会调用到
onSaveInstanceState和onRestoreInstanceState。如果是单独按Home或者启动新Activity仍然会单独触发onSaveInstanceState调用。 - 调用过程:在异常情况下,会在调用
onStop()方法之前,调用onSaveInstanceState方法保存;而新的Activity重建时,就可以通过onRestoreInstanceState方法取出之前保存的数据并恢复,onRestoreInstanceState的调用时机在onCreate()之后。
# 优先级低的Activity在内存不足被回收后怎么做可以恢复到销毁前状态 Uncompleted
# Activity四种启动模式
# standard标准模式
是默认启动的模式,每次都会新创建一个实例对象;每次发送的Intent都会创建一个新的Activity(onCreate()⟶onStart()⟶onResume()),并且将其放入返回栈的栈顶。这样每次都新建一个实例的话太浪费。
# singleTop栈顶复用模式
如果在返回栈顶发现了相同的实例则重用,不会新建;否则就新建并压入栈顶;同时Activity的onNewIntent()方法会被回调。在这个模式下,我们必须同时在onCreate()和onNewIntent()两个方法中处理好传入的Intent
# singleTask栈内复用模式
如果在整个返回栈中发现了相同的实例,就将其最上面的任务终止并移除,重用该实例,同时回调onNewIntent()方法;否则新建实例并压入栈;
# singleInstance单实例模式
允许不同的应用,进程线程等共用一个实例,无论如何应用调用该实例都会重用;即持有这个Activity的Task不能再有其它Activity的实例了;
例如,如果从这个Activity中启动另外一个不同的Activity,将会自动创建一个新的Task来存放新的Activity;如果从一个已经存在许多Activity的的Task中调用启动模式是singleInstance的Activity,这个新的Activity同样会被放在一个新的Task中。不管怎么样,都会创建一个新的Task来存放Activity。
# 什么情况下分别使用上面四种不同的启动模式 Uncompleted
# onNewIntent()调用时机
如果一个Activity的启动模式是singleTop、singleTask、singleInstance,在复用Activity时就会在「调用onStart()方法之前调用onNewIntent()方法」。作用就是让已经创建的Activity处理新的Intent。
# Activity的启动过程 Uncompleted
Fragment →