[Andorid开发艺术探索 读书笔记]Activity的生命周期和启动模式 (一)

来源:互联网 发布:异常数据的检测方法 编辑:程序博客网 时间:2024/04/29 17:24

当我们考虑Activity的生命周期时,主要从两种不同的场景状态来入手:

第一种是正常情况下生命周期分析,用任老师的话来说就是典型状态下的生命周期分析。 在这个范畴里,应该包括用户正常启动一个activity,按后退键关闭该activity,以及按home键退出等操作。


这幅Google官方给的图很好的总结了正常情况下activity的生命周期:

onCreate: 创建activity

onStart:       activity可见

onResume: activity获得焦点

onPause:    activity失去焦点

onStop:       activity不可见

onDestory:  销毁activity

这些都是一些老生长谈的东西,复习一些容易被我们忽略的细节:

1.  onRestart方法只会在activity已经调用了onStop之后才会调用,如果用户只调用了onPause,再起activity只会调用onResume。举个例子来说,现在有一个activity在调用了onCreate,onStart,onResume方法之后正常被用户使用,这时有一个对话框弹出,activity会回调onPause,这时对话框dismiss了,activity重新获取焦点在用户面前,这时只会回调onResume方法。 再考虑一个场景,有一个activity在调用了onCreate,onStart,onResume方法之后正常被用户使用,用户按后退键退出这个activity,再次进入这个activity的时候,应该会调用onRestart,onStart,onResume(这里只考虑activity没有被回收,并且再次启动访问的仍然是之前的activity的实例对象)。

2. activity A 去启动 activity B,我们根据这幅图很容易知道,activity A 会回调 onPause,onStop,onDestory, activity B 会回调onCreate,onStart,onResume。但是两个activity的回调方法逻辑上串行是怎样一个顺序呢? 正确的答案是: 会先回调activity A 的onPause, 然后回调activity B的onCreate,onStart,onResume,再回调 activity A的onStop,onDestory。

在ActivityStack类里有这样一个方法:


我们可以看到,Android在新的activity启动之前,栈顶的activity需要先onPause后,新的activity才能启动。

生命周期回调的可预见顺序允许管理两个Activity之间的切换信息。例如,当第一个Activity终止时你必须把数据写到数据库中以便下一个Activity能够读取它,那么你就应该在onPause()方法执行期间把数据写入数据库,而不是在onStop()方法执行期间。



第二种是异常情况下的生命周期分析。这里任主席主要带我们考虑了两种情形,也是最典型的两种情形。一个是当资源相关的系统配置发生改变导致activity被杀死并重新创建,另一种是资源内存不足导致低优先级的activity被杀死。


对于第一种情形,最常见的情况是屏幕的旋转和键盘是否可访问状态变化,对于第二种情形,我们不好模拟其场景,但是在android内存紧张的时候,它会按照一定的优先级回收一些优先级较低的activity。这里优先级的机制简单来说,就是 前台activity > 可见但非前台activity > 后台activity,前台activity就是正在和用户交互的activity,可见但非前台activity就是比如activity中弹出一个对话框,导致activity可见但没有焦点,无法与用户交互,换句说话就是执行了onPause, 后台activity就是已经执行了onStop的activity,比如按后退键退出的activity。


无论是哪一种情形,如果我们不做额外的配置的话,activity会被销毁,再重新创建一个新的activity,在这个销毁再重建的过程中,我们往往需要保留一些activity的信息,Google给我们提供了这样一对回调方法:onSaveInstanceState(Bundle bundle)和onRestoreInstanceState(Bundle savedInstanceState)来存储和恢复数据。我们可以在onSaveInstanceState方法里,将我们需要保存的信息写到bundle对象里面去,系统会为我们做一个序列化的保存。当activity再重启的时候,系统会将我们之前保留的bundle对象传递给onCreate方法和onRestoreInstanceState方法。这样想来,在activity重启的时候,我们既可以在onCreate方法里也可以在onRestoreInstanceState方法里读取保留的信息,这两个时机对于我们来说的区别可能在于:onCreate方法里传递来的bundle对象我们需要做非空的判断,但onRestoreInstanceState方法里传递来的bundle对象不需要做非空的判断。


让人感兴趣的一点是:不仅activity里有onSaveInstanceState方法,在View里也有这个方法。其实在保留信息这个过程中,android采用的是上层委派下层这样一个策略,一层一层的进行,将所有的view的onSaveInstanceState方法里需要保留的信息都保留下来。


值得强调的一点是:onSaveInstanceState(Bundle bundle)和onRestoreInstanceState(Bundle savedInstanceState)这一组方法,只有activity在异常状态下被销毁重启才会回调的方法,在我们最前面讲的正常状态下,是不会回调这两个方法的。


最后在考虑一点,当系统配置发生变化的时候,默认情况下,会销毁当前的activity,再重建一次。如果不希望系统这样做,解决方案大致是这样:例如,不希望在屏幕旋转的时候,activity被销毁重建,在mainfest里的这个activity下配置android:configChanges="orientation",这样在屏幕发生旋转的时候,系统会拦截到这一事件,在activity里我们可以重写onConfigurationChanged这个方法来做一些希望在拦截到屏幕发生旋转这一事件时做的工作。


1 0
原创粉丝点击