Android新启动模式之singleInstancePerTask

Posted Calvin880828

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android新启动模式之singleInstancePerTask相关的知识,希望对你有一定的参考价值。

android新启动模式之singleInstancePerTask

一.singleInstancePerTask介绍

singleInstancePerTask为android12新增的在standard、singleTop、singleTask、singleInstance之后的第五种启动模式。

Android12对于singleInstancePerTask描述如下(sdk中在platforms/android-31/data/res/values/attrs_manifest.xml路径下,源码中在frameworks/base/core/res/res/values/attrs_manifest.xml路径下):

<!-- The activity can only be running as the root activity of the task, the first activity
            that created the task, and therefore there will only be one instance of this activity
            in a task. In constrast to the @code singleTask launch mode, this activity can be
            started in multiple instances in different tasks if the
            @code FLAG_ACTIVITY_MULTIPLE_TASK  or @code FLAG_ACTIVITY_NEW_DOCUMENT is set.-->`
            <enum name="singleInstancePerTask" value="4" />

翻译为:
Activity只能作为任务栈的根Activity(第一个Activity)运行创建了任务栈,因此此Activity将只有一个实例在任务栈中。在 @code singleTask 启动模式的约束下,此活动可以在不同任务栈的多个实例中启动,如果@code FLAG_ACTIVITY_MULTIPLE_TASK 或 @code FLAG_ACTIVITY_NEW_DOCUMENT 已设置。

从中描述可以了解singleInstancePerTask的作用和singleTask几乎一样,不过singleInstancePerTask不需要为启动的Activity设置一个特殊的taskAffinity才能创建一个新的Task,即相对于默认在新任务栈中启动的singleTask。

二.singleInstancePerTask demo测试

下面做一个测验查看启动activity时任务栈的情况:
使用adb shell dumpsys activity activities | grep com.example.systemapp查看进程的activity任务栈状态。以默认standard启动模式的MainActivity来启动声明singleInstancePerTask启动模式的SingleInstancePerTaskActivity,接着再启动声明standard启动模式StandardActivity。
在MainActivity启动SingleInstancePerTaskActivity的任务栈情况如下:

Task81c692c #19 type=standard A=10147:com.example.systemapp U=0 visible=true mode=fullscreen translucent=false sz=1
* ActivityRecordd0488df u0 com.example.systemapp/.SingleInstancePerTaskActivity t19
* Taske1d436a #18 type=standard A=10147:com.example.systemapp U=0 visible=false mode=fullscreen translucent=true sz=1
* ActivityRecord35a6661 u0 com.example.systemapp/.MainActivity t18

其中由于SingleInstancePerTaskActivity为singleInstancePerTask的启动模式,会新建一条新的任务栈,可以看到有两条任务栈。
接下来在MainActivity启动SingleInstancePerTaskActivity后再从SingleInstancePerTaskActivity启动StandardActivity的任务栈情况如下:

Task81c692c #19 type=standard A=10147:com.example.systemapp U=0 visible=true mode=fullscreen translucent=false sz=2
* ActivityRecord455ff31 u0 com.example.systemapp/.StandardActivity t19
* ActivityRecordd0488df u0 com.example.systemapp/.SingleInstancePerTaskActivity t19
* Taske1d436a #18 type=standard A=10147:com.example.systemapp U=0 visible=false mode=fullscreen translucent=true sz=1
* ActivityRecord35a6661 u0 com.example.systemapp/.MainActivity t18

可以看到还是只有两条任务栈,StandardActivity存在于SingleInstancePerTaskActivity的任务栈中。
接着再从StandardActivity再去启动SingleInstancePerTaskActivity。

Task81c692c #19 type=standard A=10147:com.example.systemapp U=0 visible=true mode=fullscreen translucent=false sz=1
* ActivityRecordd0488df u0 com.example.systemapp/.SingleInstancePerTaskActivity t19
* Taske1d436a #18 type=standard A=10147:com.example.systemapp U=0 visible=false mode=fullscreen translucent=true sz=1
* ActivityRecord35a6661 u0 com.example.systemapp/.MainActivity t18

可以看到任务栈还是两条,只不过SingleInstancePerTaskActivity并不会重新创建而是走了onNewIntent,而StandardActivity和SingleInstancePerTaskActivity同为一个任务栈,因此被销毁,这点类似singleTask的作用。

注意需要在Android12的真机或者模拟器上使用此模式,否则默认为standard模式。

三.和Intent.FLAG_ACTIVITY_MULTIPLE_TASK或Intent.FLAG_ACTIVITY_NEW_DOCUMENT搭配使用

和Intent.FLAG_ACTIVITY_MULTIPLE_TASK或Intent.FLAG_ACTIVITY_NEW_DOCUMENT结合使用。SingleInstancePerTaskActivity再启动SingleInstancePerTaskActivity,则会新启动SingleInstancePerTaskActivity并创建一个新任务栈。如果不设置则只走onNewIntent的回调并不会重新onCreate。

     Intent intent = new Intent(SingleInstancePerTaskActivity.this, SingleInstancePerTaskActivity.class);
     intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
     //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
     startActivity(intent);

任务栈情况如下:

 Taskbf82c4b #29 type=standard A=10147:com.example.systemapp U=0 visible=true mode=fullscreen translucent=false sz=1
* ActivityRecordea24a0e u0 com.example.systemapp/.SingleInstancePerTaskActivity t29
* Task68f9c5f #28 type=standard A=10147:com.example.systemapp U=0 visible=false mode=fullscreen translucent=true sz=1
* ActivityRecorda528cfe u0 com.example.systemapp/.SingleInstancePerTaskActivity t28
* Taskad4567a #27 type=standard A=10147:com.example.systemapp U=0 visible=false mode=fullscreen translucent=true sz=1
* ActivityRecord86222ed u0 com.example.systemapp/.MainActivity t27

四.taskAffinity介绍

taskAffinity是指Activity的任务栈亲和度,即任务归属,代表该Activity属于哪个任务栈。
使用场景:
1.一般根据taskAffinity重新为Activity选择宿主任务栈(与allowTaskReparenting属性配合使用)
2.启动一个Activity过程中Intent使用了FLAG_ACTIVITY_NEW_TASK标记,根据taskAffinity查找或创建一个新的具有对应taskAffinity的任务栈。

注意点:taskAffinity一般与singleTask搭配使用,当启动的Activity使用standard、singleTop属性时,如果只设置一个特殊的taskAffinity,但是启动它的时候不设置FLAG_ACTIVITY_NEW_TASK,是不会创建新任务栈。指定singleInstance模式和singleInstancePerTask加上taskAffinity则为新的任务栈命名。

五.allowTaskReparenting介绍

allowTaskReparenting属性的作用是Activity的迁移。当allowTaskReparenting属性和TaskAffinity配合使用时,Activity可以从一个任务栈迁移到另一个任务栈。

迁移的规则是:从一个与该Activity TaskAffinity属性不同的任务栈中迁移到与它TaskAffinity相同的任务栈中。

举个例子:当一个应用A启动了应用B的某个Activity后,如果这个Activity的allowTaskReparenting属性设置为true,那么当应用B被启动,此Activity会直接从应用A的任务栈转移到应用B的任务栈中。
具体点来说,现在有两个应用A和B,A启动了B的一个Activity C,然后按Home键回到桌面,然后再单击B的桌面图标,这个时候不是启动了B的主Activity,而是重新显示了已经被应用A启动的Activity C。我们也可以理解为,C从A的任务栈转移到了B的任务栈中。
可以这么理解,由于A启动了C,这个时候C只能运行在A的任务栈中,但是C属于B应用,正常情况下,它的TaskAffinity值肯定不可能和A的任务栈相同,所以当B启动后,B会创建自己的任务栈,这个时候系统发现C原本想要的任务栈已经创建了,所以就把C从A的任务栈中转移过来了。

六.singleInstance和singleInstancePerTask区别

singleInstance表示全局只有一个activity实例。这个Activity得到一个唯一的Task,只有它自己在运行;如果它再次以相同的Intent启动,那么该Task将会被移动到前台,并且它的Activity.onNewIntent()方法被调用。如果这个Activity尝试启动一个新Activity,这个新活动将在一个单独的任务栈中启动。而singleInstancePerTask作用和singleTask相当,只不过会为启动的Activity新建任务栈,同时配合Intent.FLAG_ACTIVITY_MULTIPLE_TASK或Intent.FLAG_ACTIVITY_NEW_DOCUMENT,singleInstancePerTask可以同时存在Activity在不同任务栈中。


欢迎关注我的公众号“虎哥LoveDroid”,原创技术文章第一时间推送。

Android之Activity的启动模式

启动模式有4种,分别为:
1.standard(默认)  -- 标准
2.singleTop  -- 单顶
3.singleTask -- 单任务
4.singleInstance: -- 单例  -- 如果应用1的任务栈中创建了MainActivity实例,如果应用2也要激活MainActivity,则不需要创建,两应用共享该Activity实例。(单例)

这种启动模式比较特殊,它会启用一个新的栈结构,将Acitvity放置于这个新的栈结构中,并保证不再有其他Activity实例进入。 通过this.getTaskId()来显示栈结构ID。

在AndroidManifest.xml配置<activity>的android:launchMode属性为以上四种之一。

Activity_launchMode_singleInstance

SecondActivity和FourthActivity都是singleInstance模式,其他都是standard模式。

back :

FifthActivity (5) —> ThirdActivity (3) —>FirstAty (1) —>FourthActivity (4) —> SecondActivity (2)

结论:

singleInstance都会单独创建一个新的返回栈。

其余详见:

http://www.cnblogs.com/fanchangfa/archive/2012/08/25/2657012.html

运用场景:

http://blog.csdn.net/berber78/article/details/19628153

http://www.tuicool.com/articles/iIf6BbV

以上是关于Android新启动模式之singleInstancePerTask的主要内容,如果未能解决你的问题,请参考以下文章

android:Activity启动模式之singleTask

Android之Activity的启动模式

Android组件体系之Activity启动模式解析

Android之LaunchMode(启动模式)

Android--Activity四种启动模式

Android启动模式之singleinstance的坑