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的任务栈情况如下:

Task{81c692c #19 type=standard A=10147:com.example.systemapp U=0 visible=true mode=fullscreen translucent=false sz=1}
* ActivityRecord{d0488df u0 com.example.systemapp/.SingleInstancePerTaskActivity t19}
* Task{e1d436a #18 type=standard A=10147:com.example.systemapp U=0 visible=false mode=fullscreen translucent=true sz=1}
* ActivityRecord{35a6661 u0 com.example.systemapp/.MainActivity t18}

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

Task{81c692c #19 type=standard A=10147:com.example.systemapp U=0 visible=true mode=fullscreen translucent=false sz=2}
* ActivityRecord{455ff31 u0 com.example.systemapp/.StandardActivity t19}
* ActivityRecord{d0488df u0 com.example.systemapp/.SingleInstancePerTaskActivity t19}
* Task{e1d436a #18 type=standard A=10147:com.example.systemapp U=0 visible=false mode=fullscreen translucent=true sz=1}
* ActivityRecord{35a6661 u0 com.example.systemapp/.MainActivity t18}

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

Task{81c692c #19 type=standard A=10147:com.example.systemapp U=0 visible=true mode=fullscreen translucent=false sz=1}
* ActivityRecord{d0488df u0 com.example.systemapp/.SingleInstancePerTaskActivity t19}
* Task{e1d436a #18 type=standard A=10147:com.example.systemapp U=0 visible=false mode=fullscreen translucent=true sz=1}
* ActivityRecord{35a6661 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);

任务栈情况如下:

 Task{bf82c4b #29 type=standard A=10147:com.example.systemapp U=0 visible=true mode=fullscreen translucent=false sz=1}
* ActivityRecord{ea24a0e u0 com.example.systemapp/.SingleInstancePerTaskActivity t29}
* Task{68f9c5f #28 type=standard A=10147:com.example.systemapp U=0 visible=false mode=fullscreen translucent=true sz=1}
* ActivityRecord{a528cfe u0 com.example.systemapp/.SingleInstancePerTaskActivity t28}
* Task{ad4567a #27 type=standard A=10147:com.example.systemapp U=0 visible=false mode=fullscreen translucent=true sz=1}
* ActivityRecord{86222ed 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”,原创技术文章第一时间推送。
公众号二维码

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Calvin880828

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值