文章主要介绍了
Android 的为什么需要启动模式?
Android 的启动模式
Android 的启动模式使用场景
Android 的启动模式的使用

Android 中的 Activity 启动模式是什么?

Activity 为什么需要 启动模式?

我们知道在默认情况下,当我们多次启动同一个 Activity 的时候,系统会创建多个实例并把他们一一放到任务栈中。这里的栈是一种后进先出的结构,所以当我们按下 back 键时,会将最后加入的 Activity 先移出栈。

后进先出: 指的是最后进入栈内的,在移出时是最先移除的。如下:

Android 中为了在多次启动同意额 Activity 时,不重复创建多个实例,所以他提供了启动模式来修改系统的显示行为。

目前有四种启动模式:standardsingleTopsingleTasksingleInstance。那么他们表示什么含义呢?

standard (标准模式-也就是默认模式)

每次启动 Activity 时都会创建一个Activity实例,不管这个实例是否已经存在。它都会被放入任务栈中。出现的情景大概如下图所示:

singleTop (栈顶复用模式)

  • 如果新 Activity 已经位于任务栈的栈顶,那么该Actvity将不会被重新创建。同时它的 onNewIntent()方法会被回调,通过此方法我们可以取出当前请求的信息。
  • 如果新 Activity 不位于任务栈的栈顶,那么该Actvity还是会被重新创建。

简单图示如下:

singleTask(栈内复用模式)

这是一种单实例模式,在这种模式下,只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例。和singleTop一样会回调onNewIntent()方法,通过此方法我们可以取出当前请求的信息。

简单图示如下:

Android 启动已存在的activity android启动模式应用场景_启动模式

singleInstance

单实例模式,这是一种加强的singleTask模式,他除了具有singleTask模式的所有特性之外,而且具有此种模式的Activity只能单独的位于一个任务栈中。

简单图示如下:

目前在项目中的使用场景?

  • 首页使用 SingleTask模式,不使用 SingleInstance模式。
    原因是:
    (1)防止生成重复页面。
    因为首页可能不一定从点击 Iocn启动才进入,可能是从广播或者分享的网页链接点击后进入。
    (2)在使用 overridePendingTransition 启动首页页面时,如果使用SingleInstance模式会出现一段时间的白屏,推测原因可能是新建了新的任务栈导致(还未测试,忘知道的朋友告知原因)

如何使用?

第一种方式:
AndroidManifest.xml中找到要设置的activity,然后添加launchMode属性,如下:

<activity 
      android:name=".launch_model.AActivity"
      android:launchMode="standard">

第二种方式:
Java代码中设置flag标记位,通过设置的标记位可以设定Activity的启动模式,但是这种方式不能为Activity设置SingleInstance模式。

常见的和启动模式相关的标记位如下:

  • FLAG_ACTIVITY_NEW_TASK

该标志位的作用是为 Activity指定 singleTask启动模式,和在AndroidManifest.xml设置的launchMode="singleTask"的作用是一样的。

Intent intent = new Intent(MainActivity.this, AActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
  • FLAG_ACTIVITY_SINGLE_TOP

该标志位的作用是为 Activity指定 singleTask启动模式,和在AndroidManifest.xml设置的launchMode="singleTop"的作用是一样的。
该标志位的作用是为 Activity指定 singleTop启动模式,和在AndroidManifest.xml设置的launchMode="singleTop"的作用是一样的。

Intent intent = new Intent(MainActivity.this, AActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
  • FLAG_ACTIVITY_CLEAR_TOP

该标志位的作用是,当标记了该标志位的Activity启动时,在同一个任务栈中所有位于它上面的Activity都要出栈。这个标记位一般会和singleTak启动模式一起出现。

如果被启动的Activity的启动模式是standard模式,那么它连同它之上的Activity都要出栈,系统会重新创建新的实例

Intent intent = new Intent(MainActivity.this, AActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

具有这个标记的Activity不会出现在历史Activity的列表中,

Intent intent = new Intent(MainActivity.this, AActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivity(intent);

它等同于在AndroidManifest.xml设置的excludeFromRecents="true"的作用是一样的。

<activity android:name=".launch_model.AActivity"
            android:excludeFromRecents="true">

两种方式的使用区别:

  • 第二种方式的优先级高于第一种方式,如果两种方式都存在,以第二种方式为准。
  • 二者的限定范围不同。第一种方式无法直接设置FLAG_ACTIVITY_CLEAR_TOP标识;而第二种方式无法为Activity指定SingleInstance模式

参考

Android 开发艺术探索