Activity的生命周期

来源:互联网 发布:网络防诈骗的班会 编辑:程序博客网 时间:2024/05/23 19:48

四种状态

运行状态

Activity处于活动状态,此时Activity处于栈顶,是可见状态,可与用户进行交互

暂停状态

当Activity 失去焦点但仍然可见时,此时一个新的非全屏的Activity或者一个透明的Activity处于栈顶,Activity就转化为暂停状态

但我们需要明白,此时Activity只是失去了与用户交互的能力,其所有的状态信息及其成员变量都还存在,只有在系统内存紧张的情况下,才有可能被系统回收掉。

停止状态

当一个Activity被另一个Activity完全覆盖时,被覆盖的Activity就会进入停止状态,此时它不可见,但是跟暂停状态一样保持着其所有状态信息及其成员变量。

销毁状态

当Activity由于人为或系统原因(如低内存等)被销毁时。

生命周期方法流程图

这里写图片描述

生命周期方法

onCreate()

该方法是在Activity被创建时回调,它是生命周期第一个调用的方法,我们在创建Activity时一般都需要重写该方法,然后在该方法中做一些初始化的操作,如通过setContentView()设置界面布局的资源,初始化所需要的组件信息等。

onStart()

此方法被回调时表示Activity正在启动,此时Activity已处于可见状态,只是还没有在前台显示,因此无法与用户进行交互。可以简单理解为Activity已显示而我们无法看见罢了。

onResume()

当此方法回调时,则说明Activity已在前台可见,可与用户交互了(处于前面所说的运行形态),onResume()与onStart()的相同点是两者都表示Activity可见,只不过onStart()回调时Activity还是后台无法与用户交互,而onResume()则已显示在前台,可与用户交互。当然从流程图,我们也可以看出当Activity停止后(onPause()和onStop()被调用),重新回到前台时也会调用onResume(),因此我们也可以在onResume()中初始化一些资源,比如重新初始化在onPause()或者onStop()中释放的资源。

onPause()

此方法被回调时则表示Activity在暂停状态,一般情况下onStop()会紧接着被回调。但通过流程图我们还可以看到一种情况是onPause()执行后直接执行了onResume(),这属于比较极端的现象了,这可能是用户操作使当前Activity退居后台后又迅速地再回到到当前的Activity,此时onResume()就会被回调。当然,在onPause()中我们可以做一些数据存储或者动画停止或者资源回收的操作,但是不能太耗时,因为这可能会影响到新的Activity的显示——onPause()执行完成后,新Activity的onResume()才会被执行。

onStop()

一般在onPause()执行完成直接执行,表示Activity即将停止或者完全被覆盖(暂停状态),此时Activity不可见,仅在后台运行。同样地,在onStop()可以做一些资源释放的操作(不能太耗时)。

onRestart()

表示Activity正在重新启动,当Activity由不可见变为可见状态时,该方法被回调。这种情况一般是用户打开了一个新的Activity时,当前的Activity就会被暂停(onPause()和onStop()被执行了),接着又回到当前Activity页面时,onRestart()就会被回调。

onDestroy()

此时Activity正在被销毁,也是生命周期最后一个执行的方法,一般我们可以在此方法中做一些回收工作和最终的资源释放。

非典型生命周期方法

onSaveInstanceState()

onSaveInstanceState字面理解就是保存实例的状态,当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。

注意上面的双引号,何为“容易”?言下之意就是该activity还没有被销毁,而仅仅是一种可能性。这种可能性有这么几种情况:

  • 当用户按下HOME键时
    这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则。
  • 长按HOME键,选择运行其他的程序时。
  • 按下电源按键(关闭屏幕显示)时。
  • 从activity A中启动一个新的activity时。
  • 屏幕方向切换时,例如从竖屏切换到横屏时。
  • 在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行。

    总而言之,onSaveInstanceState的调用遵循一个重要原则,即当系统有可能“未经你许可”销毁了你的activity时,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。

    onRestoreInstanceState()

    onSaveInstanceState字面理解就是恢复实例的状态, 需要注意的是,onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行。

    不过大多数情况下也是很少使用onRestoreInstanceState方法的,经常我们还是在onCreate方法里直接恢复状态的,onCreate方法里本身会有一个Bundle参数的,很多时候我们是这样使用的。(onCreate在onStart之前调用,而onRestoreInstanceState是在onStart之后调用)

    但是从onCreate()的参数Bundle中恢复数据,但是需要判空,但是如果收到了onRestoreInstanceState()回调,那么其参数中的Bundle一定是非空的,因为只有onSaveInstanceState()中成功保存了数据,重新创建的生命周期才会收到onRestoreInstanceState()的回调。

    onSaveInstanceState()和onRestoreInstanceState()成对出现

    这两个生命周期只是在Activity被异常终止时成对出现(6.0以上在动态权限申请时也会出现)。Activity的异常终止大概有以下两种情况:

  • 系统配置发生改变
  • 内存不足时,优先级低的Activity资源被回收
  • 其中系统配置改变是指系统需要重新加载一些资源以适应某些配置的改变,如旋转屏幕、语言或地区改变、键盘改变等。当发生这种改变的时候,系统会重新创建这个Activity,在销毁和重新创建的过程中,这两个生命周期将会被回调。在这种情况下,系统会自动保存当前view的一些状态,然后在重新创建时恢复数据。当然,我们也可以通过onSaveInstanceState()做一些自定义的保存。

    过滤不想监听的配置变化
    如果我们不想让一些配置变化影响我们的页面,我们可以通过android:configChanges标签来过滤一些我们不想监听的配置变化。值得注意的是,这个标签的意思并不是设置需要监听哪些配置的改变,而是过滤不想监听的改变。比如,“屏幕旋转”时系统需要重新加载res中一些资源,因此默认会触发Activity的重新创建,如果我们不想让这种变化对我们的Activity产生影响,就可以通过设置android:configChanges=”orientation | screenSize”过滤屏幕旋转事件,因为屏幕旋转不但涉及到屏幕朝向的改变,还会改变屏幕展示的尺寸,因此我们需要同时过滤这两个标签。

    时序

    onSaveInstance()发生在onStop()之前,和onPause()没有固定的时序,方法注释如下:

         * <p>If called, this method will occur before {@link #onStop}.  There are     * no guarantees about whether it will occur before or after {@link #onPause}.

    onRestoreInstanceState()发生在onStart()之后,onPostCreate()之前,方法注释如下:

         * <p>This method is called between {@link #onStart} and     * {@link #onPostCreate}.

    时间图如下:
    这里写图片描述

    其他常见问题

    1.假设A Activity位于栈顶,此时用户操作,从A Activity跳转到B Activity。那么对AB来说,具体会回调哪些生命周期中的方法呢?回调方法的具体回调顺序又是怎么样的呢?

    开始时,A被实例化,执行的回调有A:onCreate -> A:onStart -> A:onResume。

    当用户点击A中按钮来到B时,假设B全部遮挡住了A,将依次执行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop。

    此时如果点击Back键,将依次执行B:onPause -> A:onRestart -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。

    2.onNewIntent()的作用?
    如果Activity的启动模式是:singleTop, singleTask, singleInstance,在复用这些Acitivity时,就会在调用onStart()前调用onNewIntent()。

    当调用到onNewIntent()的时候,需要在onNewIntent()中使用setIntent()赋值给Activity的Intent,否则,后续的getIntent()得到的都是最初的Intent。

    3.弹出一个Dialog或者Toast时,onPause()会调用吗?
    首先,如果你弹出的是本Activity的Dialog,并不会有任何生命周期方法调用。

    Dialog是一个View,它本身就依附在Acitivty上,可以理解为是属于本Activity的,所以它的焦点也自然是本Activity的焦点,自然不会有什么生命周期方法调用了。

    如果其他Activity的Dialog弹出了,onPause()才会调用。

    Toast也不会引起onPause()的调用。

    4.横竖屏切换的时候,生命周期方法是如何调用的?如何进行配置呢?

    横竖屏切换时,如果不做任何配置,生命周期方法的回调顺序为:
    onPause–onSaveInstanceState–onStop–onDestroy–onCreate–onStart–onResume

    也就是说Activity被销毁并重建了。如果不想这样可以在清单文件中的Activity添加一行配置:

        android:configChanges="keyboardHidden|orientation|screenSize"

    5.Activity调用了onDestroy(),就会在Activity的任务栈消失吗?

    一般情况下我们点击back键就回去调用当前Activity的finish()
    通常来说finish()中会执行两个操作,一是调用onDestroy(),二是将Activity从任务栈中退出

        /**     * Finishes the current activity and specifies whether to remove the task associated with this     * activity.     */    private void finish(int finishTask) {        ……    }

    只调用onDestroy(),是不会将Activity从任务栈中清除的。

    例如:手机上的“开发者选项”中有一个“不保留活动”的设置,当开启此设置,手机上的设置提示是“用户离开后即销毁每个活动”,开启后,对于其他的应用程序是从A Acticity到B Activity,然后通过Back键回到A,此时,A经过短暂的白屏(有可能黑屏等,取决于主题设置)然后变得可见。

    6.onResume()时真的可见,可交互吗
    我们来看一下onResume()方法注释的部分:

         * <p>Keep in mind that onResume is not the best indicator that your activity     * is visible to the user; a system window such as the keyguard may be in     * front.  Use {@link #onWindowFocusChanged} to know for certain that your     * activity is visible to the user (for example, to resume a game).

    其实onWindowFocusChanged()才真正地表示Activity对于用户可见了

    7.onCreate()之后一定会走之后的生命周期吗
    我们来看onCreate()的部分方法注释:

         * <p>You can call {@link #finish} from within this function, in     * which case onDestroy() will be immediately called without any of the rest     * of the activity lifecycle ({@link #onStart}, {@link #onResume},     * {@link #onPause}, etc) executing.

    我们发现可以调用finish(),跳过其他生命周期,直接从onCreate()过度到onDestroy()

    参考:
    1Android之Activity生命周期浅析(一)
    2.Activity生命周期里的“隐秘”
    3.Activity的生命周期,你足够了解吗?
    4.Android总结篇系列:Activity生命周期
    5.onSaveInstanceState和onRestoreInstanceState触发的时机

    原创粉丝点击