Activity启动模式的重点总结

前言

这里首先给大家推荐一篇文章吧,我转载的谷歌关于Activity的启动模式的官方文档

其中对Activity的启动模式,任务和回退栈进行了较为详尽的分析。

但是有一些重点可能没有很清楚地描述出来,下面就来分析一下。当然前提条件是你基本了解谷歌关于Activity的启动模式的官方文档中的内容,任务回退栈启动模式taskAffinity属性等。

taskAffinity

它是< activity >的一个重要属性,有以下特点:

1.taskAffinity指示当前 Activity 优先属于哪个任务。

2.在概念上,具有相同taskAffinity的activity(即设置了相同taskAffinity属性的activity)属于同一个任务

3.这个属性决定两件事:

  1. 当activity被reparent时,它可以被reparent到哪个任务中。
  2. 当activity以FLAG_ACTIVITY_NEW_TASK标志启动时,它会被启动到哪个任务中。

4.默认情况下,一个应用中的所有activity具有相同的taskAffinity,即应用程序的包名

我们可以通过设置不同的taskAffinity属性给应用中的activity分组,也可以把不同的应用中的activity的taskAffinity设置成相同的值。

5.只设置这一个属性没有作用,必须和Intent的Flag或者launchmode配合使用

Intent.FLAG_ACTIVITY_NEW_TASK

从源码来看,Intent.FLAG_ACTIVITY_NEW_TASK是启动模式中最关键的一个Flag,依据该Flag启动模式可以分成两类,设置了该属性的与未设置该属性的。

对于非Activity启动的Activity(比如Service中启动的Activity)需要显示的设置Intent.FLAG_ACTIVITY_NEW_TASK,而singleTask及singleInstance在AMS中被预处理后,隐形的设置了Intent.FLAG_ACTIVITY_NEW_TASK

而启动模式是standard及singletTop的Activity不会被设置Intent.FLAG_ACTIVITY_NEW_TASK,除非通过显示的intent setFlag进行设置。

FLAG_ACTIVITY_NEW_TASK这个属性更多的关注点是在Task,大多数情况下,需要将Activity引入到自己taskAffinity的Task中,Intent.FLAG_ACTIVITY_NEW_TASK的初衷是在Activity目标taskAffinity的Task中启动,非Activity(比如在Service中启动Activity)启动Activity都必须添加Intent.FLAG_ACTIVITY_NEW_TASK才行。

例子

假设我们现在要启动一个Activity TestActivity,它的taskAffinity值为com.tingshuonitiao.test,并且我们在启动的时候给Intent加上了Flag–Intent.FLAG_ACTIVITY_NEW_TASK

那么在启动它的时候,我们会做如下分析:

  • 如果存在com.tingshuonitiao.test这样的一个任务,则检查在这个任务中是否已经有了一个TestActivity的实例。

    • 如果已经存在一个TestActivity的实例,并且它是栈的根Activity,启动该Activity的Intent和当前Intent相等,则会重用这个任务和任务中的TestActivity实例,将这个任务调到前台,清除位于TestActivity上面的所有Activity,显示TestActivity,并调用TestActivity的onNewIntent()

    • 如果不满足(1)已经存在一个TestActivity的实例,(2)并且它是栈的根Activity,(3)启动该Activity的Intent和当前intent相等这三个条件中的一条,就会在这个任务中创建TestActivity新的实例,并调用onCreate()

  • 如果不存在com.tingshuonitiao.test这样的一个任务,会创建一个新的taskAffinitycom.tingshuonitiao.test的任务,并且将TestActivity启动到这个新的任务中去。

以上所指的Intent相等,就是说两次启动Activity的Intent属性要完全一样。
假设我们要启动的TestActivity是一个根Activity,正常启动应用的时候它就是应用的入口,直接就打开了。在清单文件中有如下配置:

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

那么我们现在在另一个任务中要去启动它就要给Intent加上两条对应的属性:

intent.setAction("android.intent.action.MAIN");
intent.addCategory("android.intent.category.LAUNCHER");

否则就不能满足Intent相等的要求,达不到所要的效果了。

singleTask

singleTask启动模式默认是加了Intent.FLAG_ACTIVITY_NEW_TASK这个Flag的,意味着可以在一个新的任务中开启,至于是不是真的会在新任务中开启,还要根据其他设置分析。

当然singleTask还有一点很重要的意思就是“single in task”,即在同一个任务中,只会有一个该Activity的实例

例子

还是假设我们现在要启动一个Activity TestActivity,它的taskAffinity值为com.tingshuonitiao.test,并且它的launchmodesingleTask

那么在启动它的时候,我们会做如下分析:

  • 如果存在com.tingshuonitiao.test这样的一个任务,则检查在这个任务中是否已经有了一个TestActivity的实例。

    • 如果已经存在一个TestActivity的实例,则会重用这个任务和任务中的TestActivity实例,将这个任务调到前台,清除位于TestActivity上面的所有Activity,显示TestActivity,并调用TestActivity的onNewIntent()

    • 如果不存在一个TestActivity的实例,会在这个任务中创建TestActivity的实例,并调用onCreate()

  • 如果不存在com.tingshuonitiao.test这样的一个任务,会创建一个新的taskAffinitycom.tingshuonitiao.test的任务,并且将TestActivity启动到这个新的任务中去。

allowTaskReparenting

使用的时候记得添加exported这一属性,它默认值是false,如果被设置为了false,那么这个Activity将只会被当前Application或者拥有同样user ID的Application的组件调用。

我们使用的时候修改为true,所以在清单文件中做如下配置:

            android:allowTaskReparenting="true"
            android:exported="true"

这样的话,就能成功地达到Reparenting的效果了。

以上就是很有可能混淆或者遗漏的一些重点。

本文的内容总结自我测试的demo和如下两篇文章,强烈推荐大家阅读,本文没涉及到的可以在其中找到:
1.Android中Activity四种启动模式和taskAffinity属性详解
2.Android面试官装逼失败之:Activity的启动模式

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值