Activity的生命周期,对于Android开发者来说,再熟悉不过了。但是我们接触到的资料,绝大部分都只是谈了一些表面上的东西,例如各个回调的顺序等等。本文试图换个角度来讲解,也希望对各位读者有所帮助。

1. 生命周期

首先附上一张大家都熟悉的不能再熟悉的图了

对于各个流程的回调,想必大家早已熟记于心了,对于单个Activity来说,完全没问题,复杂点的,不就是转屏嘛?能有啥,好的,下面几个问题,麻烦大家先思考下。

  1. FirstActivity启动了SecondActivity,整个流程是怎样的?
  2. setContentView如果放在onStart或者onResume中,会有什么问题吗?
  3. onPause中可以保存状态,为什么还要onSaveInstanceState,onCreate中有恢复机制,为什么还需要onRestoreInstanceState?
  4. 如何判断一个Activity真正可见

2. 来自官方

在回答这些问题之前,先来回顾下Activity的各个阶段,下面的英文部分出自Google Android官方文档

2.1 onCreate

Called when the activity is first created. This is where you should do all of your normal static set up: create views, bind data to lists, etc. This method also provides you with a Bundle containing the activity's previously frozen state, if there was one. Always followed by onStart().

直接看重点,onCreate是用来干啥的,创建view、绑定data的地方。是初始化Activity的地方,setContentView以及获取控件都应该放在这里去做。

2.2 onStart

Called when the activity is becoming visible to the user.

Followed by onResume() if the activity comes to the foreground, or onStop() if it becomes hidden.

onPause会被调用,是在Activity正在对用户变得可见的时候。也就是说这个时候,对于用户来说不是真正的可见,也不可去响应用户的输入。

2.3 onResume

Called when the activity will start interacting with the user. At this point your activity is at the top of the activity stack, with user input going to it.

Always followed by onPause().

onResume是在将要可以产生交互的时候被调用的,也就是说,还不能响应用户的输入操作。在这个阶段,Activity已经是处在栈顶了。

2.4 onPause

Called when the system is about to start resuming a previous activity. This is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, etc. Implementations of this method must be very quick because the next activity will not be resumed until this method returns.

Followed by either onResume() if the activity returns back to the front, or onStop() if it becomes invisible to the user.

onPause可以用来干啥,停止动画或者那些占用CPU操作的地方,但是在onPause里面进行的操作,不能够太久,应该very quick,因为下一个Activity需要等onPause结束后才会被调起。这个very quick的时间,应该是多少了?这个在ActivityManagerService中有定义,不能超过500ms。如果在onPause里面处理时间超过5秒的话,会不会出现ANR呢?

// How long we wait until giving up on the last activity to pause.  This
// is short because it directly impacts the responsiveness of starting the
// next activity.
static final int PAUSE_TIMEOUT = 500;

2.5 onStop

Called when the activity is no longer visible to the user, because another activity has been resumed and is covering this one. This may happen either because a new activity is being started, an existing one is being brought in front of this one, or this one is being destroyed.

Followed by either onRestart() if this activity is coming back to interact with the user, or onDestroy() if this activity is going away.

onStop的描述很简单,Activity对用户不可见时调用,但是文档后面Killable一栏显示的是YES,也就是说,onStop有可能会被强制结束掉而不完整的执行。

2.6 onDestroy

The final call you receive before your activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it, or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.

onDestroy是在Activity要被释放掉时调用的,但是这个被释放,有主动的(手动去调用finish())和被动的(系统回收),可以通过isFinishing来区分这两种场景。

2.7 onSaveInstanceState

This method is called before an activity may be killed so that when it comes back some time in the future it can restore its state.

The default implementation takes care of most of the UI per-instance state for you by calling onSaveInstanceState() on each view in the hierarchy that has an id, and by saving the id of the currently focused view (all of which is restored by the default implementation of onRestoreInstanceState(Bundle)).

If called, this method will occur after onStop() for applications targeting platforms starting with P. For applications targeting earlier platform versions this method will occur before onStop() and there are no guarantees about whether it will occur before or after onPause().

从官网的三段介绍,可以看出几点

首先,onSaveInstanceState的调用时机,它是在当前Activity可能会被杀死的时候才会触发,什么场景下会被杀死呢?当前Activity存在被回收的可能,就可能会被系统杀死。如果用户主动的去杀死当前Activity,这个方法是不会被调用的。

其次,它的作用主要是用于存储UI层面的状态,不同于onPause。

最后,这个方法的调用时机,在不同的系统中不同,从Android P开始,它是在onStop之后调用的,在之前的系统中,则是在onStop之前调用的。但是是否发生在onPause前后,则看具体情况。

2.8 onRestoreInstanceState

This method is called after onStart() when the activity is being re-initialized from a previously saved state, given here in savedInstanceState. Most implementations will simply use onCreate(Bundle) to restore their state, but it is sometimes convenient to do it here after all of the initialization has been done or to allow subclasses to decide whether to use your default implementation. The default implementation of this method performs a restore of any view state that had previously been frozen by onSaveInstanceState(Bundle).

This method is called between onStart() and onPostCreate(Bundle).

可以看出,这个方法的主要作用,是恢复在onSaveInstanceState中保存的状态。它的调用时机在onStart和onPostCreate之间。

3. 回到问题

读了谷歌官方文档,是否会发现一些平时开发中没有注意到的点呢?接下来我们回到上面的几个问题。

FirstActivity启动了SecondActivity,整个流程是怎样的?

在正常情况下,按照文档说的,首先会去调用FirstActivity的onPause方法,在onPause方法结束完毕后,然后调用SecondActivity的onCreate、onStart、onResume,最后是FirstActivity的onStop。这个是根据文档来推断的,我们实际跑一下程序。

    I/FirstActivity: =====FirstActivity=====onPause
I/FirstActivity: =====FirstActivity=====onWindowFocusChanged
I/SecondActivity: =====SecondActivity=====onCreate
I/SecondActivity: =====SecondActivity=====onStart
I/SecondActivity: =====SecondActivity=====onResume
I/SecondActivity: =====SecondActivity=====onWindowFocusChanged

从打印的log可以看出,跟推断的一样,首先调用的是FirstActivity的onPause,然后才是resume SecondActivity。

setContentView如果放在onStart或者onResume中,会有什么问题吗?

从官方文档来看,也只是说应该把setContentView放在onCreate中,并没有说必须放在这里,所以应该也不会有显示以及调用的问题吧。还是跑一下程序看看,分别将setContentView以及设置点击事件放在onStart以及onResume中,跑了下程序,没有出现显示问题。但是这个仅仅是显示上的问题,会不会存在效率的问题呢?我们来打印一下时间,以调用onCreate到onWindowFocusChanged之间的时间,作为Activity加载时间,来进行对比

    I/SecondActivity: =====SecondActivity=====Load Time:56
I/SecondActivity: =====SecondActivity=====Load Time:57
I/SecondActivity: =====SecondActivity=====Load Time:57

三次时间几乎一样的,也就是说,如果只是单丛初次启动的效率来说,在三个地方去进行setContentView是没有任何差别的。但是为甚么官方说应该放在onCreate里面去处理了,这是因为,onCreate在正常状况下,只会被调用一次,而onStart以及onResume都会被调用多次,放在这里面去做的话,在onResume的过程,会增加额外的耗时。

另外,由于onRestoreInstanceState是在onStart之后才调用的,如果将setContentView放在onResume的话,可能会产生问题。

onPause中可以保存状态,为什么还要onSaveInstanceState,onCreate中有恢复机制,为什么还需要onRestoreInstanceState?

首先,onSaveInstanceState以及onRestoreInstanceState是Android进行UI状态保存与恢复的一套单独的机制。说是单独的机制,是因为每个view里面,都会有onSaveInstanceState去进行一些默认的状态保存操作,常规状态下不需要用户去干预,比方说编辑框中输入的文本信息,这样做为开发者省了很多事。

根据官方文档来看,onPause主要的作用是停止动画以及一些耗CPU的操作,可以用于保存状态。onSaveInstanceState主要作用是对UI进行状态保存。两者的侧重点不同,onPause也可以保存UI的状态,但是,onPause设计的主要目的是和onStart配对,停止耗时操作。

onCreate中也可以恢复状态,但是onRestoreInstanceState的触发时间滞后于onCreate,在onStart之后执行,它设计的目的是用来恢复onSaveInstanceState中保存的状态。

onPause以及onCreate可以干这些事情,但是它们当初不是设计出来,专门干这个事情的。

如何判断一个Activity真正可见?

对于这个问题,其实没有严格的说法,onResume以及onWindowFocusChanged中都可以做判断,但是官方文档上说,onWindowFocusChanged是Activity对用户是否可见最好的指示器。

4. 扩展之外

好了,上面几个问题都回答了,谷歌官方文档写的非常的详细。那么,问题又来了

谷歌为什么要设计生命周期中的这几种状态呢?

从谷歌的官方文档可以看出,onStart,是通过是否可见这种状态来作为区分,onResume则是通过是否可以交互来区分,onPause设计的是与onResume相对应,onStop与onStart相对应,onCreate则是与onDestroy对应。

可以看出,谷歌在设计Activity的生命周期时,主要的依据是,是否可见以及是否可交互。那么这两种状态对于Activity来说有哪些影响呢?

仔细想想,不难看出,在正常状况下,Activity的生命周期也是根据这两个因素来运作的。失去焦点时,流程会走向onPause,获取焦点,则会走向onResume。完全不可见时,会走向onStop,后面又可见时,会去调取onStart。正常状况下的状态变换,都是围绕着这两个因素来流动的。

onCreate中做动画失效、设置属性失败的原因?

这个问题,我想stackoverflow上有非常多的解决方案,但是从根本上去说,是因为onCreate的时候,元素还不可见,所以做不了动画,一些控件无法去设置属性。

onPause中处理时间过长,是否会引起问题呢?

如果时间过长,会引发ANR。如果时间大于限定值500ms,会出现 pause timeout 的警告。

5. 最后的话

本文只是单纯的从Activity生命周期的角度,来分析一些问题,并对一些现状做了解释。当然,我所表述的有可能会有问题,欢迎大家指正。

平时接触到的书籍以及网上的资料,包括日常的开发中,这些问题的分析解答少之又少。这些问题也一直困扰着我,因此我才写了这篇文章,就最常见的东西,换个角度去看问题。我所参考的资料简单的不能再简单了,就是谷歌文档,一些结论也是依据文档中的描述所推导的。

最后感谢大家的阅读。

喜闻乐见-Activity生命周期的更多相关文章

  1. [转]: 两分钟彻底让你明白Android Activity生命周期(图文)!

    转自:http://blog.csdn.net/android_tutor/article/details/5772285 大家好,今天给大家详解一下Android中Activity的生命周期,我在前 ...

  2. Activity生命周期(深入理解)

    今天看到一篇大神总结Activity的文章,内容甚为详细,特此转载http://www.cnblogs.com/lwbqqyumidi/p/3769113.html Android官方文档和其他不少资 ...

  3. Android Activity生命周期

    从android api文档摘抄出来的activity生命周期图如下: Activity有如下四种状态 a.活动状态  activity处于屏幕前台,获取到了焦点可以和用户进行交互,同一时刻只有一个a ...

  4. Android Activity生命周期详讲

    管理 Activity 生命周期 通过实现回调方法管理 Activity 的生命周期对开发强大而又灵活的应用至关重要. Activity 的生命周期会直接受到 Activity 与其他 Activit ...

  5. android Activity生命周期(设备旋转、数据恢复等)与启动模式

    1.Activity生命周期     接下来将介绍 Android Activity(四大组件之一) 的生命周期, 包含运行.暂停和停止三种状态,onCreate.onStart.onResume.o ...

  6. android开发------Activity生命周期

    这几天工作比较忙,基本没有什么时间更新播客了. 趁着今晚有点时间,我们来简单说一下什么是Activity生命周期和它们各阶段的特征 什么是生命周期 在还没有接触android开发的时候,听到有人说Ac ...

  7. 安卓activity生命周期

    相信不少朋友也已经看过这个流程图了,也基本了解了Activity生命周期的几个过程,我们就来说一说这几个过程. 1.启动Activity:系统会先调用onCreate方法,然后调用onStart方法, ...

  8. Activity生命周期 onCreate onResume onStop onPause (转)

    Android应用开发提高系列(6)——Activity生命周期 onCreate 和 onResume 在程序启动时候都会启动, 所有有些需要在onCreate onResume中都要实现的功能,之 ...

  9. Android总结篇系列:Activity生命周期

    Android官方文档和其他不少资料都对Activity生命周期进行了详细介绍,在结合资料和项目开发过程中遇到的问题,本文将对Activity生命周期进行一次总结. Activity是由Activit ...

随机推荐

  1. JAVA基础语法——标识符、修饰符、关键字(个人整理总结)

    JAVA基础语法——标识符.修饰符.关键字 一 . 标识符 1.1    什么是标识符 就是程序员在定义java程序时,自定义的一些名字,例如helloworld 程序里关键字class 后跟的Dem ...

  2. Spring boot 参数相关注解

    最近使用swagger的在线文档调试接口时发现老是报参数问题,最后发现是方法中参数上的注解有问题,今天把填的坑做一下总结. 1. RequestParam 该注解有两个属性: name/value:表 ...

  3. windows上xshell6的安装

    各位大兄弟,好用的xshell组件来了,话不多说,开搞. 软件链接链接:https://pan.baidu.com/s/1vcRo2L-LNe2BrJ9-VCy57A 密码:ei73 有下面四个软件, ...

  4. iOS开发笔记(Swift)-针对Swift调用PPiFlatSegmentedControl项目的一些修改

    PPiFlatSegmentedControl项目是一个很流行的开源iOS控件库,提供了扁平化风格(Flat style)的SegmentedControl,可以自定义segment的颜色,图标.大小 ...

  5. OC学习4——OC新特性之块(Block)

    文章主要参考  关于OC中的block自己的一些理解(一) 对块的深入理解  浅析ios开发中Block块语法的妙用 1.关于block block的作用:保存一段代码. 苹果官方推荐的一种语法,类似 ...

  6. 写好Java代码的30条经验总结

    成为一个优秀的Java程序员,有着良好的代码编写习惯是必不可少的.下面就让我们来看看代码编写的30条建议吧. (1) 类名首字母应该大写.字段.方法以及对象(句柄)的首字母应小写.对于所有标识符,其中 ...

  7. 【原创】贡献一个JS的弹出框代码...

    一.前言 最近在做一个项目,自己感觉系统自带的alert()方法的弹出框实在是不堪入目,所以在网上找了一些资料,然后自己加工了一下,做出了自己的一个js弹出框,在这里贡献出来,希望对你有帮助. 二.开 ...

  8. 用RIPv2实现网络区域的互通

    1.动态路由的分类: DV协议:距离矢量协议 距离矢量:路由器只能够知道邻居路由的信息 LS协议:链路状态协议 链路状态:路由器能够知道所在协议内的所有信息 RIP协议的全程是:路由信息协议(DV协议 ...

  9. Java中锁分类

    锁的分类大致如下:公平锁/非公平锁可重入锁/不可重入锁独享锁/共享锁乐观锁/悲观锁分段锁 1.公平锁/非公平锁公平锁就是严格按照线程启动的顺序来执行的,不允许其他线程插队执行的:而非公平锁是允许插队的 ...

  10. JVM笔记11-类加载器和OSGI

    一.JVM 类加载器: 一个类在使用前,如何通过类调用静态字段,静态方法,或者new一个实例对象,第一步就是需要类加载,然后是连接和初始化,最后才能使用. 类从被加载到虚拟机内存中开始,到卸载出内存为 ...