相信大家对Activity并不陌生,几乎每天都在和它打交道。在最近的工作中,解决一个bug的时候,因为对activity生命周期理解有些疏忽,兜了些圈子。所以,这篇文章来对activity作一个再认识。
生命周期:
先贴张再熟悉不过的图吧:
onCreate:生命周期的第一个方法,此时activity正在被创建。一般在该方法被调用时加载布局资源以及初始化数据。
onStart:此时activity正在被启动,并进入可见状态。但是无法与用户进行交互。
onResume:一般我们所看到的activity都处于该生命周期下。此时activity可见并处于前台,与用户进行交互。
onPause:表示正在被停止,正常情况下,紧接着onStop会被调用。可以做一些停止动画等不耗时的操作。因为启动新的activity时,需要上一activity的onPause执行完成后才调用onResume。
onStop:表示即将被停止。可以做一些对象清除等不耗时操作。
onDestory:Activity即将被销毁,为生命周期的最后回调。
补充几点:
- 由Activity A跳转到Activity B的情况下,生命周期为:A onPause -> B onCreat -> B onStart -> B onResume -> A onStop
- A跳转到B后,快速回到A,对于A,由onReaume - > onPause -> onResume,不会调用onStop。不过这种情况用户难以操作出现。
- 由A跳转到B,如果B是Dialog类型的activity,也就是说B无法全部遮盖住A,那么跳转到B的过程中,对于A来说,只会调用其onPause方法,而onStop方法不会被调用。
- 在当前activity中弹出Dialog时,生命周期不会改变,即不会调用onPause.
异常销毁:
上面所涉及的是activity的典型周期,用户正常操作下的情况。但是,当我们手机的内存不足、资源改变时,activity有可能被销毁。
当activity被异常销毁时,依次调用onPause -> onStop -> onDestory,并且,在activity有机会重新创建的条件下调用onSaveInstanceState方法保存当前activity的状态。该方法会在onStop之前调用,与onPause没有既定的时序关系。值得强调的是,该方法只会在activity被异常销毁时调用,正常情况下,例如返回键消除activity时,则不会被调用。当activity被重新创建时,可以通过onCreat以及onRestoreInstanceState方法来获取异常销毁时所保存的状态。建议在onRestoreInstanceState里进行操作,该方法在onStart方法后被调用。如果在onCreate里获取状态,还需判断savedInstanceState是否为null的情况。
当activity被异常销毁时,除了我们可以重写onSaveInstanceState、onRestoreInstanceState方法进行状态的保存与恢复外,系统自身也会对当前activity视图结构进行保存,并在重新创建时进行恢复。比如TextView,在重新创建后其视图以及用户已经输入的数据都会被恢复。
关于保存和恢复view层次结构:每一个view与activity一样,都有onSaveInstanceState、onRestoreInstanceState方法。当activity异常销毁时,会调用其onSaveInstanceState保存数据,然后activity回委托windows保存数据,接着windows会委托它上面的顶层容器保存数据。顶层容器是一个ViewGroup,一般来说是一个DecorView。最后顶层容器会一一的通知其子view进行数据保存,这样说有view数据都得以保存。
内存不足:
当系统内存不足时,会销毁优先级比较低的activity。优先级从低到高分为三种:
- 后台activity,即不可见,被停止的活动;
- 可见但非前台activity,比如弹出了一个对话框,此时activity可见但无法与用户进行交互;
前台activity,正在与用户进行交互的activity,优先级最高。
系统内存不足时,系统就会按照上述优先级由低到高杀死activity对应的进程,并在后续activity创建时恢复数据。如果一个进程中没有四大组件执行,那么该进程很容易被杀死。因此,我们的后台工作一般通过service完成。
上面比较详细的讲解了activity的正常周期,以及异常情况下的状态保存与恢复。那有没有办法避免异常情况下activity重新创建呢?答案是肯定的。比如,横竖屏切换时,如果不希望我们的activity重新创建,只需要在AndroidManifest.xml的对应activity标签下添加:
android:configChanges="orientation">
如果想指定多个值,则用“|”进行区别:
android:configChanges="orientation|keyboard"
下面贴一张会比较用到的值以及其含义的表:
ok,关于activity的生命周期以及异常销毁下相关数据的保存与恢复就介绍到这里。希望能比较熟悉的掌握该知识点,为实际开发中少点踩坑作铺垫。