Activity生命周期浅析

Activity是四大组件中最常用,也是最为我们所熟悉的。它负责界面的展示以及与用户的交互。熟悉activity可以更好的帮助我们开发及优化项目。

##Activity的正常生命周期

我们先从一张图上看一看activity的生命周期:

[图片上传失败…(image-3aadc7-1542287815608)]

从图中我们可以看到activity的主要的生命周期及其对应的回调。接下来,我们先解释一下各个回调对应的是那个状态。

onCreate():activity被创建时调用,我们一般需要重写此方法,用来设置布局资源及初始化所需要的组件信息等。

onRestart:activity正在重新启动时调用,一般情况下,由用户操作导致的activity从不可见到可见的时候就会调用此方法。比如用户点击了home键或者切换到了别的activity,如果在这段时间之内此activity没有被系统回收,则再次返回时调用onRestart()方法。

onStart():activity正在启动的时候调用,这个时候表示activity已经可见了,但是无法获取用户焦点,无法与用户交互。

onResume():activity可以与用户交互的时候调用,一般在此处开启动画。在这个时候表示activity可以接收用户的输入并给予反馈,此时activity位于栈顶。

onPause():activity失去焦点的时候调用,表示activity被另一个activity或者其他控件覆盖。需要注意的是,如果是从activity B启动到activity A,那么在activity B的onPause()结束之前,activity A不回被创建。所以,不要在这个方法中执行耗时的操作。Android中指定如果0.5秒内,onPause()没有被执行完毕,则会强制关闭activity。在这个方法中,用来保存activity正在编辑的需要持久化的数据,这样在activity返回后,这些数据还可以被还原。还可以做一些如停止动画和其他大量消耗CPU的事情,以便尽快切换到下一个activity。

onStop():当activity对用户不可见的时候调用,这个时候activity处于暂停状态。如果在这之后用户重新召回该activity,则会调用onRestart()方法。

onDestory():当activity被销毁的时候调用。在这个方法中,我们要释放所有此activity所持有的引用,以保证GC可以正常的回收。

###Activity生命周期执行过程

(1) activity第一次启动: onCreate–>onStart–>onResume

(2) 用户切换到桌面或者打开其他的activity:onPause–>onStop

在此处需要注意如果新的activity的为透明主题,则不调用onStop方法。

(3) 用户再次回到原activity:onRestart–>onStart–>onResume

(4) 用户按回退键:onPause–>onStop–>onDestory

(5) 从activity A跳转到activity B:A#onPause–>B#onCreate–>B#onStart–>B#onResume–>A#onStop

(6) 从activity B返回到activity a:B#onPause–>A#onRestart–>A#onStart–>A#onResume–>B#onSop–>B#onDestory

还有一个需要注意的生命周期的方法是onWindowFocusChanged方法:在Activity获得或失去焦点时被调用。当Activity被创建时是在onResume之后被调用,当Activity被覆盖或者退居后台或者当前Activity退出时,它是在onPause之后被调用。此方法可以用来获取视图组件的大小。因为在onCreate方法中,window对象可能还没有创建完成,所以无法获取视图的大小。

##Activity异常状态下的生命周期

除了用户操作会引起activity生命周期变化意外,还有一些异常的情况也会引起activity生命周期的变化。比如,资源相关的系统配置发生改变、系统内存不足导致低优先级的activity被杀死及给activity设置了特定的启动模式等。接下来,我们就分析一下这些情况对应的activity的生命周期的执行状态。

###(1)系统配置发生改变

我们都知道,当应用程序启动时,系统会根据当前设备的情况去加载合适的资源文件。那么,如果我们的操作导致系统配置发生改变,比如横竖屏切换,在默认情况下,activity会被销毁并重新创建。请看下图:

Activity生命周期浅析_第1张图片

如果activity被异常销毁,系统会调用onSaveInstanceState(在onStop之前调用)方法保存当前activity的状态(文本输入内容、滚动视图的滚动位置等),将这些信息保存在bundle对象中。当activity被重新创建的时候,bundle对象作为参数传递给onCreate和onRestoreInstanceState方法(在onStart方法之后调用),这样我们就能够通过bundle对象恢复数据。

在这里需要注意如果在onCreate方法中恢复数据,需要对bundle对象做判空处理。因为onCreate方法在activity正常启动的时候也会被调用,这个时候bundle对象为空。所以,建议在onRestoreInstanceState方法中做数据的恢复工作。因为onRestoreInstanceState方法只有在activity因为异常状态被销毁,需要重新创建创建的时候才会被调用。所以bundle必定是有值的。

在onSaveInstanceState和onRestoreInstanceState中,系统会默认为我们保存当前的视图结构。其工作流程为:当activity被异常终止时,activity会调用onSaveInstanceState方法去保存数据。然后activity委托window去保存数据,window再委托他上层的顶级容器去保存数据,顶级容器是一个viewGroup,一般来说是DecorView。最后,顶级容器再通知他的子元素去保存数据。这样,通过这种委托思想,数据就保存下来了。恢复数据同理。

分析完之后我们想一个问题,是不是每当系统配置发生变化,activity都的重新创建一次?答案是否定的,我们可以通过设置configChanges属性来解决这个问题。

属性值 含义
mcc SIM卡唯一标识IMSI(国际移动用户标识码)中的国家代码,由三位数字组成,中国为:460 这里标识mcc代码发生了改变
mnc SIM卡唯一标识IMSI(国际移动用户标识码)中的运营商代码,有两位数字组成,中国移动TD系统为00,中国联通为01,电信为03,此项标识mnc发生了改变
locale 设备的本地位置发生了改变,一般指的是切换了系统语言
touchscreen 触摸屏发生了改变
keyboard 键盘类型发生了改变,比如用户使用了外接键盘
keyboardHidden 键盘的可访问性发生了改变,比如用户调出了键盘
navigation 系统导航方式发生了改变
screenLayout 屏幕布局发生了改变,很可能是用户激活了另外一个显示设备
fontScale 系统字体缩放比例发生了改变,比如用户选择了个新的字号
uiMode 用户界面模式发生了改变,比如开启夜间模式-API8新添加
orientation 屏幕方向发生改变,比如旋转了手机屏幕
screenSize 当屏幕尺寸信息发生改变(当编译选项中的minSdkVersion和targeSdkVersion均低于13时不会导致Activity重启)-API13新添加
smallestScreenSize 设备的物理屏幕尺寸发生改变,这个和屏幕方向没关系,比如切换到外部显示设备-API13新添加
layoutDirection 当布局方向发生改变的时候,正常情况下无法修改布局的layoutDirection的属性-API17新添加

比如横竖屏发生变化,我们不想让activity重新创建,那么只需要设置:configChanges=“orientation|keyboardHidden”

###(2)系统内存不足导致低优先级的activity被杀死

当系统内存不足的时候,系统会杀死低优先级的activity所在的进程。并通过onSaveInstanceState和onRestoreInstanceState方法来进行数据的存储和恢复。因此,如果我们的有某些比较关键的后台操作,最好可以提高其优先级避免被系统杀死。

###(3)给activity设置了启动模式

如果有对activity启动模式不了解的同学,建议先看一下Activity 启动模式。

如果我们给activity设置了singleTask的启动模式,通过Intent启动一个Activity,如果系统已经存在该activity的实例,系统就会将请求发送到这个实例上。但这个时候,系统就不会再调用通常情况下我们处理请求数据的onCreate方法,而是调用onNewIntent方法。但是如果在这之前activity被系统杀死,则还是会调用onCreate方法。所以,onCreate和onNewIntent最好调用同样的处理数据的方法。

好了,到这里,我们关于Android生命周期的分析就暂时高一段落了。有什么不对的地方,请大家多多指正。谢谢!!!

你可能感兴趣的:(android,移动开发)