喜闻乐见之Activity生命周期

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

生命周期

首先附上一张你们都熟悉的不能再熟悉的图了android

Android生命周期

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

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

来自官方

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

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().ide

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

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.ui

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

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().spa

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

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;
复制代码

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有可能会被强制结束掉而不完整的执行。

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来区分这两种场景。

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先后,则看具体状况。

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之间。

回到问题

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

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对用户是否可见最好的指示器。

扩展以外

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

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

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

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

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

onCreate中作动画失效、设置属性失败的缘由?

这个问题,我想stackoverflow上有很是多的解决方案,可是从根本上去说,是由于onCreate的时候,元素还不可见,因此作不了动画,一些控件没法去设置属性。

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

若是时间过长,会引起ANR。若是时间大于限定值500ms,会出现 pause timeout 的警告。

最后的话

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

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

最后感谢你们的阅读。

我的博客

相关文章
相关标签/搜索