基于最近阅读《Android开发艺术探索》一书,特借此书写形式来梳理学到的知识点和自我表达能力的提升。
Activity 是一个 android 应用程序组件,也是 android 四大组件之一。主要是用户和应用程序之间进行交互的一个接口,在一个 Android 应用程序中,一个 activity 通常就是一个屏幕,用户通过这个屏幕用来与应用程序交互来完成某项任务。
下面将 Activity 的生命周期分为两部分,一部分是典型情况下的生命周期,另一部分是异常情况下的生命周期。
一般来说,在正常情况下,Activity 会经历以下 7 个生命周期。
onCreate: 表示 Activity 正在被创建, 是生命周期的第一个方法.。这个方法的作用是做一些初始化工作,比如在这里使用 setContentView 加载页面布局资源,做一些控件和变量的初始化工作和所需数据等。onRestart: 表示 Activity 正在重新重启。一般情况下,当前 Activity 从不可见重新变为可见状态时,都会调用这个方法。这种情形一般都是用户的行为导致的,比如用户按下 Home 键或者打开了一个新的 Activity,当前的 Activity 就会暂停,也就是 onPause 和 onStop 被执行了,接下来用户又回到了这个 Activity,这个方法就会被调用。一般情况下,这个方法我们不做任务操作。onStart : 表示 Activity 正在被启动,这个时候 activity 已经可见,但是还没到前台,用户还无法进行交互。在这里也可以做一些初始化工作,但官方推荐在 OnCreate 中做。onResume: 表示 Activity 已经可见了,并且已经出现在前台可以进行交互活动了 。onPause: 表示 Activity 正在停止,正常情况下,紧接着,onStop 方法就会被调用。在特殊情况下,如果这个时候快速回到当前 Activity,那么 onResume 方法就会被调用。这个时候 我们可以做一些数据存储、动画停止等工作,但是不能太耗时。因为在跳转 Activity 时只有当一个 Activity 执行完了 onPause 方法后另一个 Activity 才会启动,而且 android 中指定如果 onPause 在 500ms 即 0.5 秒内没有执行完毕的话就会强制关闭 Activity。onStop:表示 Activity 即将停止,此时Activity已经不可见了,但是Activity对象还在内存中,没有被销毁。可以做一些资源的回收工作,也不能太耗时。onDestroy:表示 Activity 即将被销毁,这是 Activity 生命周期的最后一个回调方法,我们可以将最终的资源释放,以及进行一些回收工作。通过对生命周期中各个方法的含义以及作用的了解,我们再来看看下面的流程图是不是就更清晰一点了呢。 针对上方 图1-1 Activity 生命周期的切换过程图,说明几种生命周期切换情况:
针对一个特定的 Activity,第一次启动,回调如下:onCreate -> onStart -> onResume。当用户打开一个新的 Activity 或者按 Home 回到桌面的时候,回调如下:onPause -> onStop。当用户再次回到原来的 Activity ,回调如下:onRestart -> onStart -> onResume。当用户按下 back 键回退时,回调如下:onPause -> onStop -> onDestroy 。当 Activity 被系统回收后再次打开,生命周期方法回调方法和 1 一样,注意只是回调方法一样,不同的情况不代表过程都一样。从这个图我们可以看出,从整个生命周期来说,onCreate 和 onDestory 是配对的,分别标识着 Activity 的创建和销毁,并且只可能调用一次;从 Activity 是否可见来说,onStart 和 onStop 是配对的,随着用户的操作或者屏幕的熄灭和点亮,这两个方法可能会被多次调用;从 Activity 是否在前台来说,onResume 和 onPause 是配对的,随着用户操作或者屏幕的熄灭和点亮,这两个方法也可能会被多次调用。
延伸一个问题:假设当前 Activity 为 A,如果这时用户打开一个新的 Activity B,那么 B 的 onResume 和 A 的 onPause 哪个先调用呢? 解答:A 的 onPause 先执行,再执行 B 的 onResume。所以不建议在 onPause 方法中做耗时操作,从而使得新的 Activity 尽快显示出来。此问题可参考原书中对源码的解析来彻底解决此疑问,在这里就不做源码解析了,大家可以自行参考原著作。
根据手机使用过程中的常见情形,我们从以下两种情形来分析 Activity 异常情况下的生命周期过程:
这种情形最常见的就是手机屏幕发生旋转,由于系统配置发生改变,在默认没有进行配置的情况下,Activity 会被杀死销毁并重新创建。生命周期过程是酱紫的:onPause -> onSaveInstanceState -> onStop -> onDestroy -> onCreate -> onStart -> onRestoreInstanceState -> onResume。
与正常的销毁创建相比:多了数据的保存和恢复两个过程。当 Activity 在异常情况下终止时,系统会调用 onSaveInstanceState 方法将 Activity 的状态保存为一个 Bundle 对象,在 Activity 重建创建之后传递给 onRestoreInstanceState 方法和 onCreate 方法,onSaveInstanceState 方法的调用时机在 onStop 之前,与 onPause 没有既定的时序关系。当 Activity 重新创建之后,系统会调用 onRestoreInstanceState,将之前保存在 onSaveInstanceState 中的 Bundle 对象作为参数取出,进行数据恢复。onRestoreInstanceState 方法调用在 onStart 之后。由此我们可以通过判断是否调用过 onRestoreInstanceState 方法或者 onCreate 方法中的 Bundle 对象是否为 null,来判断 Activity 是否被重新创建。
这里有两个注意点:
当 Activity 被杀死并重新创建的过程中通过 onSaveInstanceState 方法保存的数据会传递给 onRestoreInstanceState 和 onCreate,也就是说,在进行数据恢复时有两种方法,一种是在 onCreate 中进行,一种是在onRestoreInstanceState 进行。但是在 onCreate 中进行数据恢复时要考虑当前 Activity 是正常启动还是重新创建,如果是正常启动,那么 onCreate(Bundle onSaveInstanceState) 方法中 onSaveInstanceState 参数为 null。官方推荐,在 onRestoreInstanceState 方法中进行数据恢复操作。前面我们强调了在默认情况下,系统配置发生改变 Activity 会被重建,也就是说,是有方法可以改变的。我们可以通过调用onConfigurationChanged 方法使得 Activity 在屏幕旋转的情况下不被重建。这个方法的调用前提是我们要在 AndroidManifest 文件中对 Activity 标签下的 android:configChanges 属性就行配置。常用的属性值有:1.orientation:屏幕方向发生改变,比如手机屏幕旋转; 2.locale:设备的本地位置发生了改变,一般指切换了系统语言; 3.keyboardHidden:键盘的可访问性发生了改变,例如用户调出了键盘。
<activity android:name=".MainActivity" android:configChanges="orientation|locale|keyboardHidden"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>当我们指定了configChanges属性时,如果指定的系统配置发生改变,不会重建Activity,但是会调用Activity的 onConfigurationChanged 方法,我们可以根据自己的需求重写这个函数。
一般情况下,Activity 的优先级如下:
前台可见 Activity可见但非后台 Activity,例如被 Dialog 遮挡的 Activity后台 Activity,执行了 onStop,不可见的 Activity一个进程中,如果没有四大组件在运行,那么这个进程很快就会被杀死。所以一些后台工作最后放在 Service 中进行操作,以提高进程优先级,不至于被轻易杀死。
本篇文章是针对 Activity 的生命周期从正常情况和异常情况两种情形下对此进行了一个过程解析,可见作为 android 四个组件之一 ,Activity 有着非常重要的作用。主要是参考和借鉴了《Android开发艺术探索》一书,如有不恰当、不充分的地方,欢迎大家指正。