Activity生命周期

Posted 第壹时间

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Activity生命周期相关的知识,希望对你有一定的参考价值。

在简述各个生命周期方法前,先总体做一下概述。我们可以从三个层面来监视Activity生命周期
完整生命周期:完整生命周期始于onCreate方法回调,止于onDestroy方法回调
可见周期:可见周期始于onStart方法回调,止于onStop方法回调
前台周期:前台周期始于onResume方法回调,止于onPause方法回调

 

 

Activity经典的生命周期流程图

此图很清晰严谨,但是官方文档对各个生命周期回调方法的描述并不是很详细,因此如果不认真研读文档,很难明白图中的生命周期方法的走向,并可能对某些方法产生误解。例如对于onStop方法,可能会有部分童鞋对其有误解,误认为Activity进入后台时回调该方法,其实进入后台时回调的是onPause方法,不可见时回调onStop方法;也有童鞋误以为onResume方法回调意味着可以进行交互,其实我们应该以public void onWindowFocusChanged (boolean hasFocus)回调中的hasFocus参数为依据来判定是否可以进行交互。
Activity可见与否与其是否处于前台是两回事,onStart 与 onStop 配对描述Activity是否可见;onPause 与
onResume 配对描述Activity是否处于前台。Activity可见并不意味着可以交互,同样的其处于前台也未必可以交互。直接的例子是,若Activity展示了Dialog,此时Activity仍处于前台,但我们却不能与Activity交互
另外,对于上述示意图中的标注2走向,我相信很多人并没有亲自验证过,因为通常你很难通过交互来复现这一场景。对于这种场景,我们可以通过代码控制来模拟:Activity A启动Activity B,在Activity B的onCreate方法中直接调用finish方法。

 

1.生命周期中各个方法的含义和作用

(1)onCreate:create表示创建,这是Activity生命周期的第一个方法,也是我们在android开发中接触的最多的生命周期方法。它本身的作用是进行Activity的一些初始化工作,比如使用setContentView加载布局,对一些控件和变量进行初始化等。但也有很多人将很多与初始化无关的代码放在这,其实这是不规范的。此时Activity还在后台,不可见。所以动画不应该在这里初始化,因为看不到……特别说明:若您在该方法内调用finish方法,则会立即触发onDestroy回调,其他生命周期不会执行。

(2)onStart:start表示启动,这是Activity生命周期的第二个方法。此时Activity已经可见了,但是还没出现在前台,我们还看不到,无法与Activity交互。在onCreate方法之后或由onStop方法被调用而导致的Activity不可见到Activity再次可见时被调用。其实将Activity的初始化工作放在这也没有什么问题,放在onCreate中是由于官方推荐的以及我们开发的习惯。

(3)onResume:resume表示继续、重新开始,这名字和它的职责也相同。此时Activity经过前两个阶段的初始化已经蓄势待发。Activity在这个阶段已经出现在前台并且可见了。官方文档指明,这里比较适合动画启动及排他性设备访问(如相机)等。

 

(4)onPause:pause表示暂停,当Activity要跳到另一个Activity或应用正常退出时都会执行这个方法。此时Activity在前台并可见,我们可以进行一些轻量级的存储数据和去初始化的工作,不能太耗时,因为在跳转Activity时只有当一个Activity的onPause方法执行完成后另一个Activity才会启动,而且android中指定如果onPause在500ms即0.5秒内没有执行完毕的话就会强制关闭Activity。从生命周期图中发现可以在这快速重启,但这种情况其实很罕见,比如用户切到下一个Activity的途中按back键快速得切回来。

(5)onStop:stop表示停止,此时Activity已经不可见了,但是Activity对象还在内存中,没有被销毁。这个阶段的主要工作也是做一些资源的回收工作。

(6)onDestroy:destroy表示毁灭,生命周期的最后一个方法,表示Activity即将被销毁这个阶段Activity被销毁,不可见,我们可以将还没释放的资源释放,以及进行一些回收工作。

(7)onRestart:restart表示重新开始,该方法触发的前提:onStop方法被调用。Activity在这时可见,当用户按Home键切换到桌面后又切回来或者从后一个Activity切回前一个Activity就会触发这个方法。这里一般不做什么操作。该方法回调之后系统会相继触发onStart和onResume方法。

 

通过上面的了解我们发现其实Activity中的方法大都是两两对应的,只有onRestart方法散发着单身狗的清香。
那么相邻的方法之间有什么区别呢?

 

2.onCreate和onStart之间有什么区别?

(1)可见与不可见的区别。前者不可见,后者可见。
(2)执行次数的区别。onCreate方法只在Activity创建时执行一次,而onStart方法在Activity的切换以及按Home键返回桌面再切回应用的过程中被多次调用。因此Bundle数据的恢复在onStart中进行比onCreate中执行更合适。
(3)onCreate能做的事onStart其实都能做,但是onstart能做的事onCreate却未必适合做。如前文所说的,setContentView和资源初始化在两者都能做,然而像动画的初始化在onStart中做比较好。

3.onStart方法和onResume方法有什么区别?

(1)是否在前台。onStart方法中Activity可见但不在前台,不可交互,而在onResume中在前台。
(2)职责不同,onStart方法中主要还是进行初始化工作,而onResume方法,根据官方的建议,可以做开启动画和独占设备的操作。

4.onPause方法和onStop方法有什么区别?

(1)是否可见。onPause时Activity可见,onStop时Activity不可见,但Activity对象还在内存中。
(2)在系统内存不足的时候可能不会执行onStop方法,因此程序状态的保存、独占设备和动画的关闭、以及一些数据的保存最好在onPause中进行,但要注意不能太耗时。

5.onStop方法和onDestroy方法有什么区别?

onStop阶段Activity还没有被销毁,对象还在内存中,此时可以通过切换Activity再次回到该Activity,而onDestroy阶段Acivity被销毁

6.为什么切换Activity时各方法的执行次序是(A)onPause→(B)onCreate→(B)onStart→(B)onResume→(A)onStop而不是(A)onPause→(A)onStop→(B)onCreate→(B)onStart→(B)onResume

(1)一个Activity或多或少会占有系统资源,而在官方的建议中,onPause方法将会释放掉很多系统资源,为切换Activity提供流畅性的保障,而不需要再等多两个阶段,这样做切换更快。
(2)按照生命周期图的表示,如果用户在切换Activity的过程中再次切回原Activity,是在onPause方法后直接调用onResume方法的,这样比onPause→onStop→onRestart→onStart→onResume要快得多。

7.与生命周期密切相关的onSaveInstanceState方法和onRestoreInstanceState方法在什么时候执行?

通过阅读源码会发现,如果调用此方法,对于目标平台从Build.VERSION_CODES.P 开始的应用程序,此方法将在onStop之后执行。对于针对早期平台版本的应用程序,此方法将在onStop之前发生,并且不能保证它将在onPause之前或之后发生。


而onRestoreInstanceState是在onStart和onPostCreate之间调用。

 

 

源码注释
 
onCreate
在Activity开始时调用。大多数初始化工作应该在这里完成:调用setContentView(int)来inflate填充Activity的UI,使用findViewById以编程方式与UI中的小部件交互,调用managedQuery(Uri、String[]、String、String[]、String)来检索要显示的数据的游标,等等。
 
您可以在这个函数中调用finish,在这种情况下,onDestroy()将在onCreate之后立即被调用,而不执行活动生命周期的其他部分(onStart、onResume、onPause等)。
 
派生类必须直接调用超类此方法的实现。如果没有,则抛出异常。
 
参数:
savedInstanceState—如果活动在之前关闭后重新初始化,则此Bundle包含它最近在onSaveInstanceState中提供的数据。注意:否则为null。
 
onRestart
当当前活动被重新显示给用户(用户已经导航回它)时,在onStop之后调用。接下来是onStart和onResume。
 
对于使用原始游标对象的活动(而不是通过managedQuery(Uri、String[]、String、String[]、String)创建它们),这通常是应该重新请求游标的地方(因为您在onStop中禁用了它)。
 
派生类必须直接调用超类此方法的实现。如果没有,则抛出异常。
 
onStart
在onCreate之后调用——或者在活动停止后,但是现在再次显示给用户,这时会在onRestart之后调用。通常后面会跟着onResume。这是一个开始绘制视觉元素、运行动画等的好地方。
 
您可以在这个函数中调用finish,在这种情况下,onStop将在onStart之后立即调用,而不会执行中间的生命周期转换(onResume、onPause等)。
 
派生类必须直接调用超类此方法的实现。如果没有,则抛出异常。
 
onRestoreInstanceState
此方法在onStart之后调用,当活动从先前保存的状态重新初始化时,在savedInstanceState中给出。大多数实现将简单地使用onCreate来恢复它们的状态,但是在完成所有初始化之后,或者允许子类来决定是否使用默认实现,在这里这样做有时会很方便。此方法的默认实现执行对任何先前被onSaveInstanceState冻结的视图状态的恢复。
 
此方法在onStart和onPostCreate之间调用。
 
onResume
在onRestoreInstanceState、onRestart或onPause之后调用,以便您的活动开始与用户交互。这是一个指示,表明活动已激活并准备接收输入。它位于活动堆栈的顶部,用户可以看到它。
 
在 Build.VERSION_CODES.Q 之前的平台版本上,这也是一个尝试打开独占访问设备或访问单例资源的好地方。从 Build.VERSION_CODES.Q 开始,系统中可以同时恢复多个活动,因此应该使用onTopResumedActivityChanged(布尔值)来代替。
 
派生类必须直接调用超类此方法的实现。如果没有,则抛出异常。
 
onSaveInstanceState
调用此方法,以便在活动被终止之前从活动检索每个实例的状态,以便可以在onCreate或onRestoreInstanceState中恢复状态(由此方法填充的Bundle将被传递给这两个方法)。
 
此方法在某个Activity可能被杀死之前调用,以便在将来某个时候它返回时可以恢复其状态。例如,如果从activity A 启动 activity B,并在某种程度上activity A 被杀死回收资源,activity A将有机会通过这种方法来保存其用户界面的当前状态,这样当用户返回活动,用户界面的状态可以通过onCreate或onRestoreInstanceState恢复。
 
不要将此方法与 activity 的生命周期回调方法混淆,例如onPause(当用户不再主动与活动交互时总是调用它)或onStop(当活动变得不可见时调用它)。调用onPause和onStop而不调用此方法的一个例子是当用户从 activity B 导航回 activity A 时:不需要在B上调用onSaveInstanceState,因为该特定实例永远不会恢复,所以系统会避免调用它。当调用onPause而不是 onSaveInstanceInstance 的一个例子是当从activity A 启动 activity B :如果在B的一生内 A 没有被杀死,A 的用户界面的状态将保持完整,那么系统可以避免调用 activity A 的 onSaveInstanceState 方法。
 
默认实现为你负责每个实例状态的大部分的UI 通过在视图层次结构中有一个id的每个view调用View.onSaveInstanceState(),并通过保存当前焦点的视图的id(所有这一切通过onRestoreInstanceState的默认实现进行恢复)。如果您重写此方法以保存未被每个单独视图捕获的其他信息,你很可能也会直接调用默认实现,否则您要准备自己保存每个视图的所有状态。
 
如果调用此方法,对于目标平台从Build.VERSION_CODES.P 开始的应用程序,此方法将在onStop之后执行。对于针对早期平台版本的应用程序,此方法将在onStop之前发生,并且不能保证它将在onPause之前或之后发生。
 
onPause
当用户不再主动与 activity 交互,但它仍然在屏幕上可见时,作为 activity 生命周期的一部分调用。与 onResume 对应。
 
当从 activity A 启动 activity B 时,将在A上调用这个回调。B 直到 A 的 onPause 方法返回时才会被创建,所以这里不要执行任何耗时的操作。
 
此回调主要用于保存 activity 正在编辑的任何持久状态,以向用户显示“就地编辑”模型,并确保在没有足够的资源启动新活动而不首先杀死该活动时不会丢失任何东西。这也是一个停止那些消耗大量CPU的事情的好地方,以便尽可能快速地切换到下一个活动。
 
在 Build.VERSION_CODES.Q 之前的平台版本上,这也是一个尝试关闭独占访问设备或释放对单例资源访问的好地方。从Build.VERSION_CODES.Q 开始,系统中可以同时恢复多个活动,因此应该使用onTopResumedActivityChanged(boolean)来代替。
 
如果一个活动是在顶部启动的,在接收到这个调用之后,您通常会接收到一个对onStop的后续调用(在下一个活动 resumed 并在上面显示之后)。但是,在某些情况下,会直接调用 onResume 而不经过 stopped 状态。在某些情况下,当 Activity 处于多窗口模式时,它也可以处于暂停状态,用户仍然可以看到它。
 
派生类必须直接调用超类此方法的实现。如果没有,则抛出异常。
 
onStop
当您对用户不再可见时调用。接下来,您将接收到onRestart、onDestroy或nothing,这取决于以后的用户活动。这是一个停止刷新UI、运行动画和其他可视化内容的好地方。
 
派生类必须直接调用超类此方法的实现。如果没有,则抛出异常。
 
onDestroy
在活动被销毁之前执行最后的清理。这可能是因为活动正在结束(有人在其上调用finish),也可能是因为系统为了节省空间而临时销毁活动的这个实例。您可以使用 isFinishing 方法来区分这两个场景。
 
注意:不要指望调用此方法来保存数据!例如,如果一个 activity 正在内容提供者中编辑数据,那么这些编辑应该在 onPause 或onSaveInstanceState 中提交,而不是在这里提交。此方法通常用于释放与某个 activity 关联的线程等资源,以便被销毁的活动在其应用程序的其余部分仍在运行时不会留下这些资源。在某些情况下,系统只会在不调用此方法(或任何其他方法)的情况下终止活动的宿主进程,因此不应该使用它来做一些在进程结束后仍然存在的事情。
 
派生类必须直接调用超类此方法的实现。如果没有,则抛出异常。
 
git地址:https://github.com/First-Time/LifeCycleDemo.git

以上是关于Activity生命周期的主要内容,如果未能解决你的问题,请参考以下文章

Activity的生命周期及常见回调顺序

Activity与Fragment的生命周期详解

Activity的生命周期

Activity横竖屏切换生命周期变化

Activity-运行状态及生命周期

Android 的生命周期