【Android】《Android开发艺术探索》学习心得(一)Activity的生命周期及启动模式探究


前言

《Android开发艺术探索》是一本Android进阶类书籍,采用理论、源码和实践相结合的方式来阐述高水准的Android应用开发要点。本书从三个方面来组织内容。
1.介绍Android开发者不容易掌握的一些知识点
2.结合Android源代码和应用层开发过程,融会贯通,介绍一些比较深入的知识点
3.介绍一些核心技术和Android的性能优化思想
---引用自GitBook

被几位师兄推荐了这本书以及《App研发录》两本Android进阶书籍,因此买了这两本书,先从《Android开发艺术探索》看起,在这里记录一下自己的学习心得。


第1章 Activity的生命周期和启动模式

这本书将Activity的生命周期分为了两个部分的内容,分别是

  • 典型情况下的生命周期:在有用户参与下,Activity所经过的Activity所进过的生命周期改变。
  • 部分异常情况下的生命周期:Activity被系统回收或者由于当前设备的Configuration发生改变从而导致Activity被销毁重建的生命周期

异常情况下的关注点与典型情况下有所不同

典型情况下的生命周期分析

正常情况下Activity会经历如下的生命周期:

1. onCreate:表示Activity正在创建。在这里做一些初始化工作,如调用setContentView加载界面布局资源,初始化Activity数据等。
2. onRestart:当前Activity从不可见状态变为可见状态时调用。一般是用户所致,如按下Home键或打开新的Activity后回到了这个Activity时,就会出现。
3. onStart:表示Activity正在被启动。这时Activity已经可见了,但没有出现在前台,无法与用户交互。一般理解为已经它已经显示出来了但我们仍然看不到
4. onResume:表示Activity已经可见了,并出现在了前台并开始活动。和onStart的区别在于onResume时已显示在了前台,我们可以看到它了
5. onPause:表示Activity正在停止,正常情况下onStop会紧接着调用。特殊情况下,用户用足够快的速度回到当前Activity,那么onResume会接着调用。这种情况是特殊情况,用户操作很难重现。此时一般做一些储存数据,停止动画的工作。但不能太耗时,否则会印象到新Activity的显示。onPause先执行完,新的Activity的onResume才会执行。
6. onStop:表示Activity即将停止,可做一些稍微重量级回收工作,不过同样不能太耗时
7. onDestroy:表示Activity即将被销毁,可以在这里做一些回收工作和最终的资源释放。

如下图:

一些情况分析
1. 对于一个特定的Activity,第一次启动,回调是这样的:onCreate=>onStart=>onResume。
2. 当用户打开新的Activity或切换到桌面时,回调是这样的:onPause=>onStop。不过有种特殊情况,如果是透明主题,这里不会回调onStop
3. 当用户回到原Activity时,回调是这样的:onRestart=>onStart=>onResume。
4. 用户按Back键回退时,回调是这样的:onPause=>onStop=>onDestroy。
5. 当Activity被系统回收后再次打开,生命周期方法回调过程与1相同
注:只是生命周期方法相同
6. 整个生命周期来说,onCreate和onDestroy是配对的,并只可能有一次调用。从Activity是否可见来说,onStart和onStop是配对的,随着用户操作,这两个方法可能调用多次。从Activity是否在前台来说,onResume和onPause是配对的,随着用户操作,这两个方法可能调用多次。

书上提到了两个问题:
1. onStart和onResume、onPause和onStop描述上看起来差不多,对我们有什么实质性不同么?

实际使用过程来说,其实差不多,甚至可以只保留一对,但要清楚他们的差别。onStart和onStop是从Activity是否可见的角度来回调,而onResume和onPause是从Activity是否位与前台来回调的,除此之外没有其他明显区别。

  1. 假设当前Activity为A,如果此时用户打开一个新Activity B,B的onResume和A的onStop哪个先执行呢?

具体源码角度的分析可以参考书中第4页到第6页的内容,从分析可以看出,启动新Activity时,旧的Activity的onPause会先执行,然后再启动新Activity。我们可以写一个例子验证一下:

运行后日志如下:

可以从日志中看出,旧Activity的onPause先被调用,之后新Acitivity才启动。由于Android官方文档中说到,不能再onPause中做重量级操作,因为必须onPause执行完成后新Acitivity才能Resume。通过分析,在onPause和onStop中不能执行耗时的操作,尤其是onPause。意味着我们应尽量在onStop中做操作,而使得新Activity尽快显示出来并切换至前台。

异常情况下的生命周期分析

Activity除了受用户操作导致的正常生命周期外,还有一些异常情况,比如当前资源相关系统配置发生改变或者系统内存不足被杀死。下面逐一分析下面的两种情况

资源相关的系统配置发生改变导致Activity被杀死并重建

首先,我们得需要了解一点系统的资源加载机制,书上做了简单的分析:当我们把一张图片放到drawable目录后,便可以通过Resources来获取这张图片。同时为了兼容不同的设备,我们可能还需要在其他的目录放置不同的图片。比如drawable-mdpi、drawable-hdpi、drawable-land等。这样,应用程序启动时,系统会根据当前设备的情况,加载合适的Resources资源,比如很拼收集3会拿到两张不同的图片(设定了landscape或者portrait状态下的图片)。比如当前Activity处于竖屏状态,如果突然旋转屏幕,默认情况下,Avtivity机会被销毁且重建,不过我们可以阻止系统重建我们的Activity。

默认情况下,如果我们Activity不做特殊处理,那么系统配置改变后,Activity就会被销毁并重建,其生命周期如图:

系统配置改变后,Activity被销毁,其onPause,onStop,onDestroy均会被调用。同事由于Activity是在异常情况下终止,系统会调用onSaveInstanceState保存当前Activity的状态。(在onStop之前,和onPause没有明显时序关系)需要注意的是,这个方法只会在Activity被异常终止的情况下调用,正常情况系统不会回调这个方法。Activity被重新创建后,系统会调用onRestoreInstanceState,并且把Activity销毁时onSaveInstanceState方法索堡村的Bundle对象作为参数同时传递给onRestoreInstanceState和onCreate方法。因此,我们可以通过onRestoreInstanceState和onCreate方法来判断Activity是否被重建了,如果重建了,就可以取出之前保存的数据并恢复。onResoreInstanceState的调用再onStart之后。

在onSaveInstanceState和onRestoreInstanceState方法中,系统自动为我们做了一定的恢复工作,当Acitivity在异常情况下需要重建时,系统会默认为我们保存当前Activity的视图结构,并在Activity重启后为我们恢复这些数据,比如TextEdit中用户输入的数据、ListView滚动的位置等。这些View相关的状态系统都能默认为我们恢复。具体针对特定的View能为我们恢复哪些数据,可以查看View的源码。

保存及恢复View层次结构:
首先,Activity被意外终止时,会调用onSaveInstanceState方法去保存数据。然后Activity会委托Window去保存数据,Window再委托他上面的顶级容器去保存数据。顶层容器是一个ViewGroup,一般来说可能是DecorView。最后顶层容器再去一一通知子元素来保存数据。这样整个数据保存过程就完成了。

这是一种典型的委托思想,在Android中有很多的应用,比如View的绘制过程,事件分发采用的都是类似思想。数据的恢复过程也是类似的。

具体的源码分析可以参考书上第10-11页的内容。

我们可以通过一个例子,来验证自己做数据储存和恢复的情况:

日志如图:

可以看出,Activity被销毁后调用了onSaveInstanceState来保存数据,重新创建后在onCreate和onRestoreInstanceState中都能正确恢复之前储存的字符串,很好地证明了我们的分析和结论。需要注意的是,onSaveInstanceState和onRestoreInstanceState方法系统只会在异常终止的时候才会调用它,其他情况下不会触发这个过程。

可能会比较疑惑的一点是,究竟用onResoreInstanceState还是onCreate方法来储存呢?其实两者均可,二者的区别仅仅是onResoreInstanceState一旦被调用,savedInstanceState一定是有值的,不用额外地判断它是否为null,而onCreate不行,必须要额外判断。这两个方法任选一个都可以进行数据恢复,但官方文档的建议是用onRestoreInstanceState方法来恢复数据。


Android Developer in GDUT