Activity生命周期

Activity生命周期总结

Posted by 袁平 on October 13, 2018

前言

Activity生命周期讲解


正文


一. 概述

本文将分析和总结各种情况下, Activity的生命周期情况, 包括正常情况下, 异常情况下(如: 用户屏幕旋转, 资源分配不足等)以及特殊情况下(如: 当Activity上覆盖对话框或者透明Activity, 当按下Home键回到桌面时, 当屏幕熄灭时)Activity生命周期的调用情况; 同时还将简述各个方法下适于做什么工作等


二. 正常情况

2.1 单独的Activity分析

如下为一张典型的Activity生命周期图(摘自官方文档); 也是正常情况下, 一个Activity的经历

Activity生命周期

记忆的时候可以通过两两配对来记

下面将结合上图讲解各个状态:

  1. onCreate(): 一个Activity启动时只调用一次, 表示Activity创建; 可以进行一些数据绑定, 类变量初始化或者上一次UI恢复等工作(通过savedInstanceState实现)

  2. onStart(): 可见, 处于后台, 不能交互

  3. onResume(): 可见, 处于前台

  4. onPause(): 时间短暂, 处于后台; 如果在onPause的时候再快速的回到当前Activity, 那么onResume会被调用(一般用户操作很难实现这一场景); 在Android7.0或者更高, 应用可以在多窗口模式下运行, 但是只要每个时刻只有一个应用可以得到焦点, 那么此时就需要暂停另一个应用(处于onPause()状态); (一个处于onPause状态的Activity可能仍然是完全可见的, 比如说在多窗口模式下); 不应该在onPause()执行数据保存工作, 因为该阶段非常短暂, 同时只有onPause()执行完, 新ActivityonResume()才会执行

  5. onStop(): 不可见, 可以执行一些稍微重量级的工作, 比如资源释放与数据保存

  6. onDestroy(): 表示Activity销毁, 可以做一些最终的回收工作和资源释放

  7. onRestart(): 表示当当前Activity从不可见重新变为可见状态时调用

2.2 Activity启动新Activity分析

这里以Activity A正常启动Activity B的情况分析

A启动B的时候, 会依次执行A.onPause() –> B.onCreate() –> B.onStart() –> B.onResume() –> A.onStop()

可以看出, 只有当AonPause()方法执行完成之后, B的一系列方法才会调用; 这也说明了onPause()方法中不能执行耗时操作, 因为新ActivityonResume()是在其之后执行的, 如果onPause()中执行太耗时的操作的话, 会影响新Activity的显示; 我们应当尽量在onStop()中操作, 使新Activity尽快显示出来并出现在前台


三. 异常情况

3.1 资源相关系统配置改变导致Activity被杀死并重新创建

默认情况下, 如果不做特殊处理, 当系统配置发生改变之后, Activity就会被杀死并重建; 比如: 当手机进行横竖屏切换的时候, Activity默认就会被销毁重建

在这种情况下, Activity会依次调用onPause –> onSaveInstanceState –> onStop –> onDestroy –> onCreate –> onStart –> onRestoreInstanceState –> onResume

需要注意的是这里和正常情况下不同的是, 需要等到Activity销毁之后才能开始重新创建; 另一个就是, 在Activity销毁的时候, 会调用onSaveInstanceState来保存当前Activity的状态, 该方法的调用在onStop之前, 但是和onPause没有既定的时序关系; 但是onRestoreInstanceState的调用确是在onStart之后, 有既定的时序关系;

Activity销毁重建保存数据的方法是: 委托下级子元素调用其自己的onSaveInstanceState来保存自己的状态和数据; 即让其关联Window保存数据, Window再委托子View进行数据保存, 最终会调用每个子ViewView.onSaveInstanceState()来保存自己的数据

当进行数据恢复的时候, onCreate中的Bundle savedInstanceState参数不为null, 可以在此处进行数据恢复, 但是推荐在onRestoreInstanceState中进行数据恢复

3.2 资源内存不足导致低优先级Activity被杀死

  1. Activity优先级:
  1. 前台Activity: 正在和用户交互的Activity, 优先级最高
  2. 可见但非前台Activity: 比如Activity中弹出了一个对话框, 导致Activity可见但是位于后台, 无法与用户直接交互
  3. 后台Activity: 已经被暂停的Activity, 比如执行了onStop, 优先级最低

Activity被杀死的可能性如下:


四. 特殊情况

4.1 按下Home键或者当屏幕熄灭

这种情况下会调用onPause –> onSaveInstanceState –> onStop; 需要注意的是这里仍然调用了onSaveInstanceState; 但是该情况下是不会调用onRestoreInstanceState, 原因下面说明

关于onSaveInstanceStateonRestoreInstanceState调用的几点说明:

  1. onSaveInstanceState的调用: onSaveInstanceState会在当Activity有可能被销毁的时候调用, 用于进行数据保存; 注意, 只要是Activity有可能被销毁都会调用方法; 比如: 按下Home键或者屏幕熄灭Activity进行后台的时候, 该Activity可能被回收, 所以此时会调用onSaveInstanceState

  2. onRestoreInstanceState的调用和onSaveInstanceState的调用不一定是成对的, onRestoreInstanceState要调用的前提是当前Activity确实被系统销毁了

4.2 透明对话框或者透明Activity

  1. 当在Activity上覆盖一层透明对话框的时候, 不会使Activity进入后台(不会调用任何方法), 但是Activity不可和当前用户交互

  2. 当当前Activity启动一个透明Activity的时候, 会调用前一个ActivityonPause, 但是不会调用前一个ActivityonStop, 此时前一个Activity可见但是处于后台


五. 补充

  1. 考虑Activity A跳转到B的情况: 如果A跳转到B(使用startActivityForResult()), A被回收的之后再初始化, 此时从B返回, 那么AonActivityResult()是否还会调用: 参考博客; 结果如下:

在跳转后前一个页面被回收的情况下, 再回到前一个页面, onActivityResult依然会被调用, 而且是在onCreateonRestoreInstanceState两个状态恢复结点之后调用, 所以只要做好状态的保存和恢复工作, 就不用担心在onActivityResult回调时 因相关数据丢失而造成的异常了

  1. 单纯的使用startActivityForResult()的生命周期经历情况是:
    1. B onPause
    2. A onActivityResult
    3. A onRestart
    4. A onStart
    5. A onResume
    6. B onStop
    7. B onDestroy
  2. A启动B, B返回到A, 经历:
    1. A onPause (—-> A启动B)
    2. B onCreate
    3. B onStart
    4. B onResuem
    5. A onStop
    6. B onPause(—–> B返回A)
    7. A onRestart
    8. A onStart
    9. A onResume
    10. B onStop
    11. B onDestroy

六. 注

验证代码参见: Github