Android启动模式之singleTask解析「建议收藏」

Android启动模式之singleTask解析「建议收藏」在android应用程序中,最重要的组件之一Activity有4中启动模式,其中singleTask更加官方文档的描述很容易让人迷惑,其实原因在于,activity的启动方式除了受标签android:launchMode的影响之外,还会被启动参数所左右比如,intent的标志位FLAG_ACTIVITY_NEW_TASK,任务标签 android:taskAffinity。本文将对singleTa

大家好,又见面了,我是你们的朋友全栈君。

        在android应用程序中,最重要的组件之一Activity有4种启动模式,其中singleTask根据官方文档的描述很容易让人迷惑,主要是启动后所处的Task易让人困惑,其实原因在于,activity的启动方式除了受标签android:launchMode的影响之外,还会被启动参数所左右,比如intent的标志位FLAG_ACTIVITY_NEW_TASK,任务标签 android:taskAffinity。本文主要对singleTask和这些影响影响因素进行测试。

        测试代码不用复杂即可说明问题,使用两个app,假定为app A 和 app B,其中app A 有两个activity,MainActivity和SingleTaskActivity, app B只有个一个MainActivity。然后分别通过两个MainActivity来启动SingleTaskActivity进行测试。

Test 1:

        为了进行对比,先将SingleTaskActivity的属性设置为默认模式,并且不设置标签android:taskAffinity:

<activity 
            android:name=".SingleTaskActivity">
            <!--android:taskAffinity="com.zj.task">
            android:launchMode="singleTask"-->
            <intent-filter >
                <action android:name="com.zj.test.launch_singletask"/>  
                <category android:name="android.intent.category.DEFAULT"/>   
            </intent-filter>
</activity>

        在app A和app B 中分别以默认方式和FLAG_ACTIVITY_NEW_TASK的方式启动SingleTaskActivity,MainActivity主要测试代码为(App A中和App B中的一样),使用两个Button以两种方式启动Activity:

		findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent intent = new Intent("com.zj.test.launch_singletask");  
				Bundle bundle = new Bundle();
				bundle.putString("mainact", "1_Button1");
				intent.putExtras(bundle);
				startActivity(intent); 
			}
		});
		
		findViewById(R.id.button2).setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent intent = new Intent("com.zj.test.launch_singletask");  
				intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
				Bundle bundle = new Bundle();
				bundle.putString("mainact", "1_Button2");
				intent.putExtras(bundle);
				startActivity(intent);
			}
		});

Log输出位置:

App A MainActivity:

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		Log.d("SingleTask", "App A's MainActivity " +"所在的任务的id为: " +  getTaskId());
	}

App A SingleTaskActivity:

<strong>	</strong>@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		Log.d("SingleTask", "App A's SingleTaskActivity " +"所在的任务的id为: " +  getTaskId());
	}

App B  MainActivity:

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		Log.d("SingleTask", "App B's MainActivity " +"所在的任务的id为: " +  getTaskId());
	}

测试步骤为:

        1.启动App A,点击Button1,然后点击back,点击button2,然后home键,启动app B,点击Button1,然后点击back,点击button2。 

        2.启动App A,点击Button1,然后点击back,点击button2,然后点击back,然后home键,启动app B,点击Button1,然后点击back,点击button2。

Android启动模式之singleTask解析「建议收藏」

测试结果:

        在App A 中两种启动方式中,SingleTaskActivity都和启动它的MainActivity位于同一个Task,也就是说FLAG_ACTIVITY_NEW_TASK根本没有发挥作用,
        在App B 中两种启动方式中,当不设置FLAG_ACTIVITY_NEW_TASK时,SingleTaskActivity和启动它的MainActivity位于同一个Task,设置了以后,复用了已经存在位于App A中的SingleTaskActivity。

Android启动模式之singleTask解析「建议收藏」

        如果在启动App B前,先点击back从SingleTaskActivity返回后再home键的效果也一样(实际上是在目标App A的Task内新建的了一个)。

Android启动模式之singleTask解析「建议收藏」

        如果是先测试App B后测试App A的话,依然是在App A 中FLAG_ACTIVITY_NEW_TASK没有发挥作用(没有新建task),App B中则发挥了作用(区别在于, 由于App A后启动,所以App B新建SingleTaskActivity的Task时,无法再App A的Task中新建,因为它还不存在)。

Android启动模式之singleTask解析「建议收藏」

Test 2:

下面把SingleTaskActivity标签android:taskAffinity设置上内容 ,launchMode保持不变,如下(注意 app A 和 app B的包名不能和android:taskAffinity一样,否则起不到测试效果

        <activity 
            android:name=".SingleTaskActivity"
            android:taskAffinity="com.zj.task">
            <!--android:launchMode="singleTask"-->
            <intent-filter >
                <action android:name="com.zj.test.launch_singletask"/>  
                <category android:name="android.intent.category.DEFAULT"/>   
            </intent-filter>
        </activity>

        然后再次重复测试步骤:

测试结果:

        先App A,再App B(home之前不回退SingleTaskActivity):

Android启动模式之singleTask解析「建议收藏」

       在两个app下FLAG_ACTIVITY_NEW_TASK都起作用(对于app B而言,新建的时候发现目标Task的栈顶已经有一个实例,所以没有新建)。

        先App A,再App B(home之前回退SingleTaskActivity):
Android启动模式之singleTask解析「建议收藏」

       在两个app下FLAG_ACTIVITY_NEW_TASK都起作用,且新建了Task。

        先App B,在App A,结果和上面一样。

Android启动模式之singleTask解析「建议收藏」 Android启动模式之singleTask解析「建议收藏」

        好了,有些乱了吧,已经快把自己绕进去了,对于启动模式的前两种standardsingleTop(可以被实例化多次), 结论如下:

        1.如果启动者和被启动者在同一app下(声明在同一个AndroidManif.xml文件里),必须同时使用FLAG_ACTIVITY_NEW_TASK和标签android:taskAffinity才能在新的Task中启动,缺少其中的一个都会和启动者位于同一个Task。
        2.如果启动者和被启动者不在同一个app下,如果不用FLAG_ACTIVITY_NEW_TASK,则二者位于同一个Task内。如果使用的话,会新建Task,所新建的位置依据标签android:taskAffinity而定(1.如果不指定则在被启动者所在App的Task内新建,当然前提是这个被启动者所在的App的Task已经存在,2.如果目标Task内的栈顶已经有一个实例,这时候实际上不新建的,相当于要新建的内容已经存在了)。

       

        以上是一个对比测试,下面转入本文主题,对singleTask模式的测试,

Test 3::

首先依然不设置标签android:taskAffinity,启动模式为singleTask

        <activity 
            android:name=".SingleTaskActivity"
            android:launchMode="singleTask">
            <!--android:taskAffinity="com.zj.task"> -->
            <intent-filter >
                <action android:name="com.zj.test.launch_singletask"/>  
                <category android:name="android.intent.category.DEFAULT"/>   
            </intent-filter>
        </activity>

测试结果:

        先App A,再App B (不管是否回退都一样)

Android启动模式之singleTask解析「建议收藏」Android启动模式之singleTask解析「建议收藏」

Android启动模式之singleTask解析「建议收藏」

        在App A 中两种启动方式,SingleTaskActivity都和启动它的MainActivity位于同一个Task,也就是说FLAG_ACTIVITY_NEW_TASK根本没有发挥作用,而且singleTask也没有启动新Task。
       在App B 中两种启动方式:不管是否设置FLAG_ACTIVITY_NEW_TASK时,SingleTaskActivity和启动它的MainActivity都不位于同一个Task中(如存在,直接调用,如不存在,则在所属app的Task中新建出来)。


        先App B,再App A:
Android启动模式之singleTask解析「建议收藏」

       App B的两种方式都会新建一个Task任务来启动SingleTaskActivity,如不回退,启动App A时则直接进入到App B启动好的SingleTaskActivity


Test 4:

下面把SingleTaskActivity标签android:taskAffinity设置上内容

        <activity 
            android:name=".SingleTaskActivity"
            android:launchMode="singleTask" 
            android:taskAffinity="com.zj.task" >
            <intent-filter >
                <action android:name="com.zj.test.launch_singletask"/>  
                <category android:name="android.intent.category.DEFAULT"/>   
            </intent-filter>
        </activity>

       先App A,再App B:
Android启动模式之singleTask解析「建议收藏」

        先App B,再App A:
Android启动模式之singleTask解析「建议收藏」

       不管启动者和被启动着是否在同一app下,都会新建一个任务来启动SingleTaskActivity,且如果已经存在一个实例的话,就不会再次新建了。

结论:对于singleTask启动方式而言,

1.如果启动者和被启动者属于不同app的话,则只要系统中不存在这个类的实例,都会为SingleTaskActivity新建Task来启动它,存在的话就直接调用已存在的这个实例。
2.如果启动者和被启动者属于同一个app,需要设置标签android:taskAffinity以后,才会新建Task来启动,否则直接调用者所在Task内启动。


总结一下,singleTask启动方式Activity在系统中只会存在一份实例,启动时是否启动新Task,取决两个因素:启动者和被启动者的位置关系 和 标签android:taskAffinity的值。

初次发博说明代码实验,有些混乱,敬请见谅。



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/153279.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 关于easyadmin的表单提交

    关于easyadmin的表单提交由于使用的是layui,所以用法如下html代码:<divclass=”layui-btnlayui-btn-smlayui-btn-successbtnYuyue”data-seenum=”{$vo.see_num}”data-fee=”{$vo.doctor_price}”data-time=”{$vo.start_time}-{$vo.end_time}”data-id=”{$vo.time_id}”>预约</div><scripttyp.

    2025年5月27日
    5
  • 创建与删除索引

    创建与删除索引

    2021年11月13日
    67
  • vue项目引入外部原生js文件_php引入文件的四个方法

    vue项目引入外部原生js文件_php引入文件的四个方法在开发Vue项目的时候,有时需要使用一些非ES6格式的没有export的js库,可以有如下方法实现:1.在index.html页面使用script标签引入当然也可以使用cdn的地址。这样引入后的内容是全局的,可以在所有地方使用。<!DOCTYPEhtml><html> <head> <title>Map</title> <metacharset=”utf-8″> <meta

    2022年10月8日
    2
  • 苹果Mac允许安装未知来源的应用「建议收藏」

    苹果Mac允许安装未知来源的应用「建议收藏」打开终端,输入命令密码是你的开机密码允许安装未知来源的应用允许sudospctl–master-disable不允许sudospctl–master-enable

    2025年8月19日
    3
  • 怎么用python3画烟花?代码是什么?[通俗易懂]

    怎么用python3画烟花?代码是什么?[通俗易懂]我们可以用python做很多好玩的事情哦~包括制作动态的视频,之前小编就教大写编写过制作内容,现在给大家想到了更好玩的事情,就是编写个烟花代码出来,有兴趣的小伙伴可以看下呢~实施步骤:一、导入海龟

    2022年7月5日
    41
  • 我的 Java 自学之路[通俗易懂]

    我的 Java 自学之路[通俗易懂]其实在转正之后我就想抽个时间好好的梳理一下我的Java上车之路,但是一直拖到现在,因为有学弟问到,所以也就给了我动力。毕竟答应了人家的事要做到。首先要有相应的背景介绍,不然说个毛线啊,大家不在同一水平,不好参考借鉴。我呢,学校很牛逼,是一所刚过线的二本,自身的成绩在班里也就第8名左右吧(一共60个人),在大二的时候学校开设了Java这门课,我的期末考试…

    2022年7月7日
    21

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号