Activity的启动模式——LanuchMode(二)

前言:上一篇大致介绍了常规情况下我们的启动模式的运行效果,这一篇讲讲Activity运行的一些基本配置和标志。

在singleTask启动模式中,多次提到某个Activity所需的任务栈,什么是Activity所需要的任务栈呢?这要从一个参数说起:TaskAffinity,可以翻译为任务相关性。这个参数标识了一个Activity所需要的任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用的包名。当然,我们可以为每个Activity都单独指定TaskAffinity,这个属性值必须不能和包名相同,否则就相当于没有指定。TaskAffinity属性主要和singleTask启动模式或者allowTaskReparenting属性配对使用,在其他情况下没有意义。另外,任务栈分为前台任务栈和后台任务栈,后台任务栈中的Activity位于暂停状态,用户可以通过 切换后台任务栈再次调到前台。

当TaskAffinity和singleTask启动模式配对使用的时候,它是具有该模式的Activity的目前任务栈的名字,待启动的Activity会运行在名字和TaskAffinity相同的任务栈中。

当TaskAffinity和allowTaskReparenting结合的时候,这种情况比较复杂,会产生特殊的效果。当一个应用A启动了应用B的某个Activity后,如果这个Activity的allowTaskReparenting属性为true的话,那么当应用B被启动后,此Activity会直接从应用A的任务栈转移到应用B的任务栈中这还是很抽象,再具体点,比如现在有2个应用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的任务栈中转移过来了。这种情况读者可以写个例子测试一下,这里就不做示例了。

如何给Activity指定启动模式呢?有两种方法,第一种是通过AndroidMenifest为Activity指定启动模式,如下所示

     <activity
            android:name=".view.activity.home.SplashActivity"
            android:configChanges="keyboard|keyboardHidden"
            android:launchMode="singleTask"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="adjustUnspecified|stateHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

另一种情况是通过在Intent中设置标志位来为Activity指定启动模式,比如:

        Intent intent=new Intent();
        intent.setClass(MainActivity.this,ActivityB.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);

这两种方式都可以为Activity指定启动模式,但是二者还是有区别的。首先,优先级上第二种方式的优先级要高于第一种,当两种同时存在时,以第二种方式为准;其次,上述两种方式在限定范围上有所不同,比如,第一种方式无法直接为Activity设定FLAG_ACTIVITY_CLEAR_TOP标识,而第二种方式无法为Activity指定singleInstance。

上述四种启动模式,standard和singleTop都比较好理解,singleInstance由于其特殊性也好理解,但是关于singleTask有一种情况需要再说明一下,继续讲解 Activity的启动模式——LanuchMode(一)中提到singleTask Activity A,B,C,D的退栈问题,如果在ActivityB中请求的不是D而是C,那么情况如何呢?这里可以告诉读者的是,任务栈列表变成了ABC,是不是很奇怪呢?ActivityD被直接出栈了。下面我们再用实例验证看看是不是这样。首先还是使用上面的代码,我的AndroidManifest.xml里配置是这样的。

     <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:configChanges="orientation"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SecondActivity"
            android:configChanges="orientation"
            android:taskAffinity="com.rxt.task1"
            android:launchMode="singleTask"
            ></activity>

        <activity android:name=".ThirdActivity"
            android:configChanges="orientation"
            android:taskAffinity="com.rxt.task1"
            android:launchMode="singleTask"
            ></activity>

我们将SecondActivity和ThirdActivity都设成singleTask并指定它们的taskAffinity属性为”com.rxt.task1”,注意这个taskAffinity属性的值为字符串,并且中间必须含有包名分隔符”.”。(这里我只列出AndroidManifest.xml,代码和布局文件需要大家自己写)然后做如下操作,在MainActivity中单击按钮启动SecondActivity,在SecondActivity中单击按钮启动ThirdActivity,在ThirdActivity中单击按钮又启动MainActivity,最后再在MainActivity中单击按钮启动SecondActivity,现在按2次back键,然后看到的是哪个Activity?答案是回到桌面。是不是有点摸不到头脑了?没关系,接下来我们分析这个问题。

首先,从理论上分析这个问题,先假设MainActivity为A,SecondActivity为B,ThirdActivity为C。我们知道A为standrad模式,按照规定,A的taskAffinity值继承自Applaction的taskAffinity,而Applaction默认taskAffinity为包名,所以A的taskAffinity为包名。由于我们在XML中为B和C指定了taskAffinity和启动模式,所以B和C是singleTask模式并且有相同的taskAffinity值”com.rxt.task1”。A启动B的时候,按照singleTask的规则,这个时候需要为B重新创建一个任务栈”com.rxt.task1”。B再启动C,按照single的规则,由于C所需的任务栈(和B为同一个任务栈)已经被B创建,所以无需再创建新的任务栈,这个时候系统只是创建C的实例后将C入栈了。接着C再启动A,A是standrad模式,所以系统会为它创建一个新的实例并加到启动它的那个Activity所在的任务栈,由于是C启动了A,所以A会进入C的任务栈中并位于栈顶,这个时候已经有两个任务栈了,一个是名字为报名的任务栈,里面只有A,另一个是名字为”com.rxt.task1”的任务栈,里面的Activity为BCA。接下来,A再启动B,由于B是singleTask,B需要回到任务栈的栈顶,由于栈的工作模式为”后进先出”,B想要回到栈顶,只能是CA出栈,所以,到这里就很好理解了,如果再按back键,B就出栈了,B所在的任务栈已经不存在了,这个时候只能是回到后台任务栈并把A显示出来。注意这个A是后台任务栈的A,不是”com.rxt.task1”的任务栈A,接着再继续back,就回到桌面了。分析到这里我们得出一条结论,singleTask模式的Activity切换到栈顶会导致它之上的栈内的Activity出栈。

分析到这里,相信大家对Activity的启动模式已经有很深入的理解了。具体的运用还需要我们大家在实战中针对具体的情况加以分析来运用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值