浅析Activity生命周期和启动模式

一、Activity堆栈Task盖概念

Android开发的朋友应该都听过Activity堆栈Task。但是有多少人研究过这个Task?或者说了解过这个Task呢?它是属于应用的还是属于系统的?Task是如何管理Activity的?这些问题都需要我们一一的去弄明白。

1、首先要明确一个概念:Activity是属于Application的。但是Task是属于系统的,它是跨应用的。

 当用户触摸应用启动器中的图标(或主屏幕上的快捷方式)时,该应用在栈顶的任务将出现在前台。 如果应用不存在任务(应用最近未曾使用),则会创建一个新任务,系统就会默认为我们创建一个任务栈,用于存储当前程序的activity,默认所有的activity属于一个任务栈。并且该应用的“主”Activity 将作为堆栈中的根 Activity 打开。当然了,一个应用实际上除了这个默认的任务栈外还能有其他的栈。这个下面在讲启动模式的时候会讲到。

2、从用户角度,怎么看当前系统有哪些Task呢?

相信大家都见过下面这张图的情景,我们自己完手机的时候,按一下Menu键用来清理最近任务的长遇见。但是否有人知道这些一个个的小快捷方式实际上就是一个个Task呢?

 3、从开发者角度如何查看当前有哪些Task

作为开发者应该都会在Cmd中敲ADB命令吧。那么敲下如下命令就能够查看当前终端有哪些Task了。

adb shell dumpsys activity activities | sed -En -e '/Stack #/p' -e '/Running activities/,/Run #0/p'

 二、各种启动方式之间的区别

想打开一个应用的方式基本有如下几种:

  • 点击应用图标启动
  • 点击通知启动
  • 从网络链接启动
  • 从第三方应用启动
  • 点menu键,从最近使用的快捷方式启动

而前四种都可以理解为重新创建(也就是StartActivity),而最后一种只能算是恢复。创建和恢复最大的区别就是创建会走OnCreate等初始化流程,而恢复只是从后台的不可见状态恢复为可见状态。但是也不是所有创建类启动方式每次都会执行OnCreate等初始化流程。这个需要结合下面的生命周期来讲解。

三、Activity生命周期如何理解

这个在网上一堆的文章,其实有的讲的已经相当详细了。但是为什么我们每次看完后感觉自己明白了,然后过段时间又忘了呢?原因就是我们没有自己去理解每个周期的作用以及相邻相对周期之间的关系。我们先来看一下官方给的生命周期表。

 如果这样就对着图看是不是很枯燥,而且完全无法理解?那我们就需要讲这些生命周期基本的进行整理。如下:

可以发现,我们讲几个重要的生命周期从创建到销毁,进行关系映射的整理。然后我们需要弄清楚这些相邻周期之间的关系。

1、onCreate和onStart之间有什么区别?

(1)可见与不可见的区别。前者不可见,后者可见。

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

2、onStart方法和onResume方法有什么区别?

(1)是否在前台。onStart方法中Activity可见但不在前台,不可交互,而在onResume在前台,可进行交互。

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

3、onPause方法和onStop方法有什么区别?

(1)是否可见。onPause时Activity可见,onStop时Activity不可见,但Activity对象还在内存中。

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

4、onStop方法和onDestroy方法有什么区别?

(1)、onStop阶段是Activity进入不可见的阶段,但是Activity还存于堆栈中。而onDestory阶段是Activity被销毁的阶段,一般用来释放一些资源,之后Activity会被从堆栈中退出,被垃圾回收。

(2)、onStop执行时,onDestory不一定会执行。但是onDestory执行之前onStop一定会执行。

 在实际开发过程中,除了上面整理的基本生命周期外,还有几个常用的生命周期这里需要说一下,onSaveInstanceState、onRestoreInstanceState和onNewIntent().

1、onSaveInstanceState:

(1)、在Activity被覆盖或退居后台之后,系统资源不足将其杀死,此方法会被调用;

(2)、在用户改变屏幕方向时,此方法会被调用;

(3)、在当前Activity跳转到其他Activity或者按Home键回到主屏,自身退居后台时,此方法会被调用。第一种情况我们无法保证什么时候发生,系统根据资源紧张程度去调度;第二种是屏幕翻转方向时,系统先销毁当前的Activity,然后再重建一个新的,调用此方法时,我们可以保存一些临时数据。onSaveInstanceState的调用顺序是在onStop之后(这在网上很多误人子弟的文章说onSaveInstanceState的执行顺序在onPause之前,但经本人验证,这种说法时错误的)。

2、onRestoreInstanceState:

(1)、onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的,只有某个Activity真实被系统销毁过又重新启动的时候才会去调用onRestoreInstanceState。如用户改变屏幕方向时,如果当前Activity没有对屏幕旋转做处理,那么当前Activity会被销毁并重建,重建过程中会调用此方法,这时候我们可以重写此方法,以便恢复之前在onSaveInstanceState保存的一些临时数据。onRestoreInstanceState的调用顺序是在onStart之后。

3、onNewIntent:

(1)、当Activity的启动模式LaunchMode不是standard的时候(因为standard模式的Activity每次都会重新创建,所以不会执行该方法),且Activity被启动过,正处于Activity堆栈中(后台模式)时,这个时候再次启动这个Activity将会执行onNewIntent方法。

(2)、有种特殊情况下,并不符合上面的描述,就是从最近使用的应用快捷方式启动来恢复应用(官方名词是:Navigation切换回来)时,都不会执行onNewIntent方法。

(3)、该方法最常用的场景就是DeepLink的时候(也就是从网页中打开应用)来重新获取Intent中新的携带数据。

三、四种启动模式

关于Activity的启动方式,网上更是无数文章。但是别人写再好,我们看完后过几天还是忘记了。总是记不住他们之间的区别和知识点。所以通过自己的理解写一遍很有必要。

1、standard 默认模式

系统在启动 Activity 的任务中创建 Activity 的新实例并向其传送 Intent。Activity 可以多次实例化,不管这个实例是否在任务栈中已经存在,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例。这种模式的 Activity 被创建时它的onCreate、onStart 都会被调用。这是一种典型的多实例实现,一个任务栈中可以有多个实例,每个实例也可以属于不同的任务栈。在这种模式下,通常谁启动了这个 Activity,那么这个 Activity 就运行在启动它的那个 Activity 所在的栈中。这种模式下Activity启动需要注意如下几点:

  • 当从非Activity的context启动activity时,需要带new_task的flag;
  • 当启动一个带有affinity的activity,如果这个activity已经有实例存在该task,则不会重新创建,这种情况有点类似下面的singleTask启动模式;

c、如果从应用内启动的standard activity的Affinity就是App默认的Affinity,则会每次新建一个实例;

2、singleTop模式

这种模式也叫做栈顶复用模式,啥意思呢?就是说如果栈顶已经又一个相同类型的Activity实例啦,则不再重新创建实例,而是复用栈顶实列。通过onNewIntent()将新的Intent信息传递过去。如果栈顶没有该实例或者有实例但是不在栈顶,都会重新创建实例。下图是整理关于singleTop模式启动Activity的判断和调用流程。

 3、singleTask模式

这是一种栈内复用模式。在这种模式下,只要 Activity 在一个栈中存在,那么多次启动此 Activity 都不会重新创建实例,和 singleTop一样,系统也会回调其 onNewIntent。当一个具有 singleTask 模式的Activity请求启动后,比如 Activity A,系统首先会寻找是否存在 A想要的任务栈,如果不存在,就重新创建一个任务栈,然后创建 A 的实例后把 A 放到栈中。如果存在 A 所需的任务栈,这时要看 A 是否在栈中有实例存在,如果有实例存在,那么系统就会把 A 调到栈顶并调用它的 onNewIntent 方法(这个过程会将A上面的Activity都做退栈处理),如果实例不存在,就创建 A 的实例并把 A 压入栈中 。我们同样可以通过流程图来看看它的启动流程。

 4、singleInstance模式

这是一种系统内单例模式,系统不会将任何其他 Activity 启动到包含该实例的任务中。该 Activity 始终是其任务栈内唯一仅有的成员;由此Activity 启动的任何 Activity 均在单独的任务中打开。也就是有此种模式的 Activity 只能单独地位于一个任务栈中。

发布了29 篇原创文章 · 获赞 3 · 访问量 890

猜你喜欢

转载自blog.csdn.net/LVEfrist/article/details/101755695