Activity的启动模式

Activity的启动模式可以解决我们日常开发中的一些需求场景,比如我们想复用Activity,不想每次启动一个Activity的时候都要重新创建一个。

一:基础概要
Task: task 为 Activity 的集合,我们通常称任务栈。当我们启动一个 app 时,系统会默认帮我们建立一个任务栈,名称为App的包名。

二:Activity的四种启动模式

  1. standard: 标准模式,为系统默认的启动模式,每次启动activity的时候都会重新创建一个。

2.singleTop: 栈顶复用模式。当Activity已这种方式启动的时候,如果要启动的Activity位于栈顶,那么不会重新创建一个新的Activity,而是调用onNewIntent()
方法传入新的数据。

3.singleTask: 栈内复用模式。在这种模式下,只会存在一个Activity实例,重复启动的时候,会将该Activity置于栈顶。之前位于该Activity之上的Activity会出栈并销毁。

4.singleInstance:单实例模式。处于此种模式下的Activity 在Task 中仅仅只会有它一个。

三:实例分析
我们可以借助 adb shell dumpsys activity这个命令,该命令可以打印出Android的Activity任务栈,这样对我们理解启动模式更加简明。(在terminal 下使用该命令时,需要配置 adb 对应路径的环境变量)

TaskAffinity: 该属性用来指明 activity 所属的 task 的名称,属性值默认为包名。

在不指定的情况下,当启动模式为SingleTask的时候,首先会判断该属性字符串指定名字的 task是否存在,如果不存在,则会新建一个。如果存在了,则不会在新建 task。下面用例子来说明

  1. SingleTask启动Activity
    这个例子很简单,我们以默认方式启动一个Activity,然后在以SingleTask模式启动一个SecondActivity
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
  Stack #1:
    Task id #5995
      TaskRecord{7c5de36 #5995 A=com.xinwa.androidbase U=0 sz=2}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.xinwa.androidbase/.MainActivity (has extras) }
        Hist #1: ActivityRecord{ac9ab20 u0 com.xinwa.androidbase/.SecondActivity t5995}
          Intent { flg=0x10000000 cmp=com.xinwa.androidbase/.SecondActivity }
          ProcessRecord{cb84137 6694:com.xinwa.androidbase/u0a34}
        Hist #0: ActivityRecord{33c5331 u0 com.xinwa.androidbase/.MainActivity t5995}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.xinwa.androidbase/.MainActivity (has extras) }
          ProcessRecord{cb84137 6694:com.xinwa.androidbase/u0a34}

前面在说到TaskAffinity的时候,我们说到如果不指定TaskAffinity属性的时候,该属性值默认为应用包名。这里我的应用包名为“com.android.xinwa.androidbase”。从上面打印的信息可以看到。有一个Task id为#5995.这个Task就是我们的存放Activity的任务栈,其中有俩条记录,分别表示MainActivity和SecondActivity。并且能看到启动该Activity对应的Intent。

在启动SecondActivity的时候,会判断“com.android.xinwa.androidbase”这个Task是否存放,这里在启动MainActivity的时候已经创建了Task。所以在启动SecondActivity时,无需创建新的Task,放入MainActivity的Task中即可。

  1. SingleTask 和 taskAffinity属性搭配使用
    同样是在MainActivity中启动SecondActivity,给SecondActivity设置TaskAffinity属性为“com.android.xinwa.task1”。让我们看下打印结果
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
  Stack #1:
    Task id #5998
      TaskRecord{92d0e1 #5998 A=com.xinwa.task1 U=0 sz=1}
      Intent { flg=0x10000000 cmp=com.xinwa.androidbase/.SecondActivity }
        Hist #0: ActivityRecord{d336fa1 u0 com.xinwa.androidbase/.SecondActivity t5998}
          Intent { flg=0x10000000 cmp=com.xinwa.androidbase/.SecondActivity }
          ProcessRecord{21d1cc7 8379:com.xinwa.androidbase/u0a34}
    Task id #5997
      TaskRecord{92dae06 #5997 A=com.xinwa.androidbase U=0 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.xinwa.androidbase/.MainActivity }
        Hist #0: ActivityRecord{9ef8e2b u0 com.xinwa.androidbase/.MainActivity t5997}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.xinwa.androidbase/.MainActivity }
          ProcessRecord{21d1cc7 8379:com.xinwa.androidbase/u0a34}

从输出结果中,可以看到,存在俩个Task,#5998和#5997,SecondActivity这时候位于Task id #5998 ,其task名字为“com.android.xinwa.task1”。在启动SecondActivity时,taskAffnity属性指定的Task不存在,这时候就新创建task,将Activity放入其中。

  1. 当启动的 Activity 的启动模式指定为 SingleTask 时,并且该 Activity 在后台已经存在,那么启动时会将 task 在内的其他 Activity 一起带到前台,并加入回退栈里面。
Activity的启动模式_第1张图片
6951561804597_.pic_thumb.jpg
  1. 其他例子


    Activity的启动模式_第2张图片
    6961561819396_.pic.jpg

上图的执行顺序为:Acitivty A -> Activity B -> Acitivty C -> Activity D
其中 Activity C 的启动模式为 SingleTask,且指定 TaskAffinity,这里是 Task B.

场景1: Activity D 启动 Activity B,此时回退栈中 Activity 为


这个很好理解,我们要启动的 Activity B 为标准模式,则在当前 task 中新建一个,此时回退栈中的数量也就变成了 5 个。

场景2: 这里我们令 Activity B的启动模式为 SingleTask,不指定 TaskAffinity,同样是 Activity D 启动 Activity B,此时回退栈为

当启动 Activity B 为,由于 Activity B 的模式为 Single Task,故查看是否有 Activity B 在其他 Task 内已存在,如果存在,则会将该 task 内的在 Activity B 之下的其他 Activity 一同带到前台,同时回退栈中的顺序也会更新。

倘若这里启动的不是 Activity B, 而是启动的 Activity A(启动模式为 SingleTask)m, 那么回退栈内的顺序从下到上则变为 Activity C -> Activity D -> Activity A

你可能感兴趣的:(Activity的启动模式)