欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Activity 的启动模式

程序员文章站 2022-06-15 23:31:23
基于最近阅读《Android开发艺术探索》一书,特借此书写形式来梳理学到的知识点和自我表达能力的提升。...

基于最近阅读《Android开发艺术探索》一书,特借此书写形式来梳理学到的知识点和自我表达能力的提升。

Activity 的启动模式

  Activity 作为四个组件之首,其形形色色的启动模式和标注位实在是太容易被混淆了,但是它的的确确非常重要。有时候为了满足项目业务的特殊需求,就必须使用 Activity 的启动模式和标志位。

一、Activity 之 LaunchMode

  先来说一个问题,Activity 为什么需要启动模式?
  我们都知道,在默认情况下,当我们多次启动同一个 Activity 的时候,系统会创建多个实例并把它们一一加入任务栈,当我们单击 Back 键,这些 Activity 会一一回退。任务栈是一种“后进先出”的结构,就是每当我们按一下 Back 键就会有一个 Activity 出栈道,直到栈空为止,当栈中再无任何 Activity 时,系统就会回收这个任务栈。这个时候我们就会发现一个问题,多次启动同一个 Activity ,系统重复创建多个实例?所以 Android 在设计的时候不可能不考虑这个问题,所以它提供了启动模式来修改系统的默认行径。目前有4种启动模式:standard、singleTop、singleTask 和 singleInstance,先来介绍一个它们的含义:

1. standrad:标准模式,也是系统的默认模式。

  每次启动一个 Activity,系统就会重新创建一个新的实例,不论这个实例是否已经存在。这是一个典型的多实例实现,一个任务栈中可以有多个实例,每个实例也可以属于不同的任务栈,在这种模式下,谁启动了这个 Activity,那么这个 Activity 就运行在启动它的那个 Activity所在的栈中。比如 Activity A 启动了 Activity B,那么 B 就会进入到 A 所在的栈中。这里有个注意点,当我们使用 ApplicationContext 去启动 standard 模式的 Activity 的时候会报错,错误如下:

Caused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

  这是因为 standard 模式的 Activity 会默认进入到启动它的 Activity 所属的任务栈中,但是由于非 Activity 类型的 Context (如 ApplicationContext)并没有所谓的任务栈,所以这就有问题了。解决这个问题的办法是为待启动的 Activity 指定 FLAG_ACTIVITY_NEW_TASK 标记位,这样启动的时候就会为它创建一个新的任务栈,这个时候启动的 Activity 实际上是以 singleTask 模式启动。

2. singleTop:栈顶复用模式。

  在这种模式下,如果新 Activity 已经位于任务栈的栈顶,那么此 Activity 不会被重新创建,同时它的 onNewIntent 方法会被调用,通过此方法的参数我们可以获取当前请求的信息。这里要注意,这个 Activity 的 onCreate、onStart 因没有发生改变,所以不会被系统调用。如果新的 Activity 的实例已经存在但是不是位于栈顶,那么新 Activity 仍然会重新创建。举个例子,假设目前 ABC 3个 Activity,A 位于栈底,C 位于栈顶,这个时候假设要再次启动 C,如果 C 的启动模式为 singleTop,那么栈内的情况仍然为 ABC,如果 C 的启动模式为 standard,由于 C 被重新创建,导致栈内的情况变为 ABCC。

3. singleTask:栈内复用模式。

  这是一种单实例模式,在这种模式下,只要 Activity 在一个栈中存在,那么多次启动此 Activity 都不会重新创建实例,和 singleTop 一样,系统也会回调它的 onNewIntent 方法。具体一点,当一个具有 singleTask 模式的 Activity 请求启动后,比如 Activity A,系统首先会寻找是否存在 A 想要的任务栈,如果不存在,就重新创建一个任务栈,然后创建 A 的实例后把 A 放入栈中。如果存在 A 所需要的任务栈,这时要看 A 是否在栈中有实例存在,如果实例存在,那么系统就会把 A 调到栈顶并回调它的 onNewIntent 方法,如果实例不存在,就创建 A 的实例并放入栈中。

4. singleInstance:单实例模式。

  这个模式可以理解为一种加强的 singleTask 模式。它除了具有 singleTask 模式的所有特性外,还加强了一点,那就是具有此模式的 Activity 只能单独的位于一个任务栈中。比如 Activity A 是 singleInstance 模式,当 A 启动后,系统会为它创建一个新的任务栈,然后 A 独自在这个新的任务栈中,由于栈内复用的特性,后续的操作均不会创建新的 Activity 实例,除非这个独特的任务栈被系统销毁了。

  我们已经了解了4种启动模式的含义,那么如果给 Activity 指定启动模式呢?有两种方法,第一种是通过 AndroidMenifest 为 Activity 指定启动模式,如下所示。

<activity>
	android:name=".SingleTopActivity"
	android:label="@string/singletop"
	android:launchMode="singleTop" />

另一种情况就是通过在 Intent 中设置标志位来为 Activity 指定启动模式,比如:

Intent intent = new Intent();
intent.setClass(MainActivity.class,SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

  这两种方式都可以为 Activity 指定启动模式,但是二者还是有区别的。首先,从优先级上来讲,第二种方式的优先级要高于第一种,当两种同时存在时,以第二种方式为准;其他,上述两种方式在限定范围内有所不同,比如,第一种方式无法直接为 Activity 设置 FLAG_ACTIVITY_CLEAR_TOP 标识,而第二种方式无法为 Activity 指定 singleInstance 模式。

二、Activity 之 Flags

  Activity 的 Flags 有很多,这里我们主要分析一些比较常用的标记位。

1. FLAG_ACTIVITY_NEW_TASK

为 Activity 指定 “singleTask” 启动模式,其效果和在 XML 中指定效果相同。

2. FLAG_ACTIVITY_SINGLE_TOP

为 Activity 指定 “singleTop” 启动模式,其效果和在 XML 中指定效果相同。

3. FLAG_ACTIVITY_CLEAR_TOP

  具有此标记位的 Activity,当它启动时,在同一个任务栈中位于它上面的 Activity 都要移出栈。这个标记位一般会和 singleTask 启动模式一起出现,在这种情况下,被启动的 Activity 的实例如果已经存在,那么系统会调用它的 onNewIntent 方法。如果被启动的 Activity 采用 standard 启动模式,那么它连同它之上的 Activity 都要移出栈,系统会创建你的 Activity 实例并放入栈顶。

4. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

  具有此标记位的 Activity 不会出现在历史 Activity 的列表中,当某些特殊情况下我们不想让用户通过历史列表回到我们的 Activity 的时候这个标记位比较有用。它等同于在 XML 中指定 Activity 的 属性 android:excludeFromRecent=“true”。

  
  
  本篇文章主要介绍了Activity的启动模式和标记位。主要是参考和借鉴了《Android开发艺术探索》一书,如有不恰当、不充分的地方,欢迎大家指正。

本文地址:https://blog.csdn.net/qq_34530915/article/details/107459651

相关标签: Android 面试