android 当中taskAffinity属性与launchMode相关
一、本文尝试解释以下问题
1. Activity被启动之后放在哪个任务栈当中?与哪些因素有关?
2. Activity的四种启动模式对Activity的启动有哪些影响?
3. 在Activity中使用startActivityForResult(intent, REQUESTCODE);和onActivityResult()
是否与被启动的Activity的launchMode有关?如果有关,有什么关系?
二、Activity被启动之后放在哪个任务栈当中?与哪些因素有关?
1.基本论断:Activity启动之后对应的任务站与Activity的两个属性taskAffinity和allowTask-
Reparenting有关
2.原理
(1)任务栈的标识----任务栈名称的确定
任务栈的标识是由任务栈的名称来确定的,例如,在通常情况下用包名标识一个唯一任务栈,清单文件如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.musictest01"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="17" /><applicationandroid:allowBackup="true"android:theme="@style/AppTheme" ><activityandroid:name="com.example.musictest01.MainActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity android:name=".AActivity"></activity><activity android:name=".BActivity"></activity></application>
</manifest>
该文件当中<appliacation>和<activity>标签都没有设置taskAffinity属性,所以这个应用的默认任务栈名称就是包名"com.example.musictest01" , activity默认也会放入这个任务栈当中。
<application>当中的属性android:taskAffinity指定该应用程序默认的任务栈名称,用来标识一个唯一的任务栈,如果不设置,则默认为包名
<activity>当中的属性android:taskAffinity指定该activity的“宿主”任务栈名称
(2)情景分析:
第一步、定义宿主工程,其Manifest.xml文件如下:(由ADT创建,不做任何修改)
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.master"……><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme"><activityandroid:name="com.example.master.MainActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>
第二步、定义奴隶工程,Manifest.xml如下(根activity加android:taskAffinity="com.example
.master")
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.slave"……><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid:name="com.example.slave.MainActivity"android:label="@string/app_name"android:taskAffinity="com.example.master"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name=".AActivity"></activity><activity android:name=".BActivity"></activity></application></manifest>
第三步、结果
当我们启动宿主工程,按home键将宿主任务栈放到后台,然后启动奴隶工程,神奇的事情发生了:奴隶工程的MainActivity并没有被加载,而是显示的是宿主工程的MainActivity
第四步、 同样道理,反过来执行,我们首先启动奴隶工程,MainActivity-->AActivity-->BActivity,按home键,回到桌面启动宿主工程,结果并没有加载宿主工程的MainActivity,而是显示的是奴隶工程的BActivity.
第五步、结论
android:taskAffinity="com.example.master" 此属性指定了该activity所在的任务栈名称,如果系统当中已经存在指定的任务栈,那么该activity启动的时候会重新寄宿到宿主当中(这是android的官方说明,但是在实际的实践中发现,启动该activity的时候仅仅是将指定的任务栈推到前台,显示该任务栈最顶端的那个原activity,本activity并没有被创建,换言之,该activity的生命周期的相关方法并没有被执行);
如果系统当中没有指定的任务栈,那么系统会创建名为com.example.master 的任务栈,并将该activity放入到创建的任务栈当中。
第六步、诡异的事情:按照android官方文档的说明,宿主的activity当中应该要设置android:allow-
TaskReparenting="true",但是实验表明,不设置该属性亦可!
3. 与启动模式相结合的情景
3.1 android:taskAffinity 与 FLAG_ACTIVITY_NEW_TASK结合
(1)基本论断
如果加载某个Activity的intent,Flag被设置成FLAG_ACTIVITY_NEW_TASK时,它会首先检查是否存在与自己taskAffinity相同的Task,如果存在,那么它会直接宿主到该Task中,如果不存在则重新创建Task。
(2)测试。
我们首先写一个应用,它有两个Activity(Activity1和Activity2),AndroidManifest.xml如下:
<application
android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Activity1"
android:taskAffinity="com.example.task"
android:label="@string/app_name">
</activity>
<activity android:name=".Activity2">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Activity2的代码如下:
public class Activity2 extends Activity {
private static final String TAG = "Activity2";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Intent intent = new Intent(this, Activity1.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
return super.onTouchEvent(event);
}
}
//将activity1的启动模式改为new task ,并设置android:taskAffinity="com.example.task"
然后,我们再写一个应用MyActivity,它包含一个Activity(MyActivity),AndroidManifest.xml如下:
<application
android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MyActivity"
android:taskAffinity="com.example.task"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
我们首先启动MyActivity,然后按Home键,返回到桌面,然后打开Activity2,点击Activity2,进入Activity1(他的启动模式是new_task)。然后按返回键。
我们发现,我们进入Activity的顺序为Activity2->Activity1,而返回时顺序为Activity1->MyActivity。这就说明了一个问题,Activity1在启动时,重新宿主到了MyActivity所在的Task 中去了。
3.2 android:taskAffinity 与singleTask结合
直接给结论:
当一个应用程序加载一个singleTask模式的Activity时,首先该Activity会检查是否存在与它的taskAffinity相同的Task。
(1)、如果存在,那么检查是否实例化,如果已经实例化,那么销毁在该Activity以上的Activity并调用该Activity的onNewIntent()。如果没有实例化,那么该Activity实例化并入栈。
(2)、如果不存在,那么就重新创建Task,并入栈。
3.3 android:taskAffinity 与singleInstance结合
直接给出结论:
(1)、当一个应用程序加载一个singleInstance模式的Activity时,如果该Activity没有被实例化,那么就重新创建一个Task,并入栈,如果已经被实例化,那么就调用该Activity的onNewIntent;
(2)、singleInstance的Activity所在的Task不允许存在其他Activity,任何从该Activity加载的其它 Actiivty(假设为Activity2)都会被放入其它的Task中,如果存在与Activity2相同affinity的Task,则在该 Task内创建Activity2。如果不存在,则重新生成新的Task并入栈。
(3) 如果在奴隶应用application1当中定义两个activity,MainActivity和AActivity,将AActivity的启动模式设置为singleInstance,并设置其taskAffinity为com.example.master; 从MainActivity中启动AActivity,毫无疑问,此时会创建一个新的任务栈,名称是com.example.master,并将AActivity放置到栈中。然后将application1置于后台(按HOME键)。
打开宿主应用application2(默认的任务栈名称是com.example.master),此时惊奇地发现:此应用打开的是application1的AActivity,按后退键,退回到application2的MainActivity,由此可以看出,当声明为singleInstance的activity所在的任务栈被其他应用程序使用的时候,这个任务栈里面的原activity会丧失原来的singleInstance要求的一个activity在一个任务栈当中的属性,但是请注意:原来的这个activity始终是在栈顶的,后来加入的activity会都在这个activity的下面,但是还是按照栈的形式进出规则!
(4)将上面的过程反过来,如果首先启动application2,系统当中存在了com.example.master 任务栈,然后启动SingleInstanceActivity,虽然他指定了taskAffinity,但是仍然不能将自己寄宿到com.example.master任务栈当中!他会重新开一个任务栈将自己放进去!
三、Activity的四种启动模式对Activity的启动有哪些影响?
重点说一下 singleTask,直接给结论:
1. 设置了"singleTask"启动模式的Activity,它在启动的时候,会先在系统中查找属性值affinity,等于它的属性值taskAffinity的任务栈是否存在存在;如果存在这样的任务栈,它就会在这个任务栈中启动,否则就会在新任务栈中启动。因此,如果我们想要设置了"singleTask"启动模式的Activity在新的任务中启动,就要为它设置一个独立的taskAffinity属性值。
2. 如果设置了"singleTask"启动模式的Activity不是在新的任务中启动时,它会在已有的任务中查看是否已经存在相应的Activity实例,如果存在,就会把位于这个Activity实例上面的Activity全部结束掉,即最终这个Activity实例会位于任务的堆栈顶端中(这个过程会调用该Activity的onNewIntent())。
四、在Activity中使用startActivityForResult(intent, REQUESTCODE);和onActivityResult()
是否与被启动的Activity的launchMode有关?如果有关,有什么关系?
1.通常情况下,当launchMode设置为standard或者singleTop的时候,程序的执行流程如下所示
2.如果launchMode设置为singleTask或者singleInstance的时候,程序就会在setResult之前调用
onActivityResult(),这样就得不到从activity2返回的数据,所以需要注意!!!
转自:http://my.oschina.net/u/1865711/blog/289663
android 当中taskAffinity属性与launchMode相关相关推荐
- 【Android 应用开发】Activity 任务亲和性 taskAffinity 设置 ( taskAffinity 属性 )
文章目录 I . 任务亲和性 ( taskAffinity ) 简介 II . 任务亲和性 ( taskAffinity ) 设置 III . 任务亲和性 ( taskAffinity ) 与 FLA ...
- android控件属性
android控件属性 控件属性: android属性 Android功能强大,界面华丽,但是众多的布局属性就害苦了开发者,下面这篇文章结合了网上不少资料, 第一类:属性值为true或false an ...
- 【Android控件属性记录】
#Android 控件属性记录 方便查找 控件属性: android属性 android功能强大,界面华丽,但是众多的布局属性就害苦了开发者,下面这篇文章结合了网上不少资料, 第一类:属性值为true ...
- android 软键盘的从属关系,Android控件属性大全
控件属性: android属性 Android功能强大,界面华丽,但是众多的布局属性就害苦了开发者,下面这篇文章结合了网上不少资料, 第一类:属性值为true或false android:layout ...
- Activity的taskAffinity属性
Activity的taskAffinity属性 - Android - ITeye技术网站 Activity的归属,也就是Activity应该在哪个Task中,Activity与Task的吸附关系.我 ...
- Android Activity标签属性
Android Activity标签属性 Activity 是 Android 系统四大应用组件之一,用户可与 Activity 提供的屏幕进行交互,以执行拨打电话.拍摄照片.发送电子邮件等操作开发者 ...
- Android 高级面试-2:IPC 相关
内容 IPC 就是指跨进程通信.IPC 相关的内容,涉及的主要有: 常见的 IPC 通信方式: Binder 相关: 两种序列化方式及其对比: 问题 IPC Android 上的 IPC 跨进程通信时 ...
- Android--应用开发3(Android layout XML属性)
Android layout XML属性 转载:http://www.cnblogs.com/playing/archive/2011/04/07/2008620.html Layout对于迅速的搭建 ...
- 【错误记录】未安装该应用 ( 在 Android 12 之后 组件设置 android:exported=“false“ 属性 )
文章目录 一.报错信息 二.解决方案 一.报错信息 报错信息 : 点击应用图标后 , 应用并未启动 , 并弹出 " 未安装该应用 " 提示信息 ; 二.解决方案 排查了一下相关地方 ...
最新文章
- 2020年PMCAFF大咖分享合集(有回放)
- 如何实现分类表统计数目和详情表数量同步
- boost::function_types::is_function_reference的测试程序
- 15分钟从零开始搭建支持10w+用户的生产环境(一)
- RS232与串口通信的4个注意事项详解
- springboot 监听所有异常_SpringBoot——目前Java开发最流行的框架(一)
- 助农两年销量千万 “李佳琦公益”实现“造血式”帮扶
- KL散度(双向KL散度) JS散度
- UEditor 实现新增“转换简体”和“转换繁体字”按钮功能
- word转化为html操作步骤
- Oracle优化器详解,通宵整理,透彻超详细
- (赠票)2021年佛山敏捷之旅暨第1届佛山DevOps社区Meetup
- 将sublime右下角永远改为HTML格式
- 情人辞职信 [搞笑,也来个好玩的乐一乐]
- [自习任我行]第二阶段任务跟踪1
- Win11安卓子系统(WSA)怎么卸载?
- 让吹牛都能全世界最棒
- 如何安装虚拟机linux
- 日常计算机桌面系统的维护,新手学电脑日常维护与故障排除
- docker容器无法访问宿主机报出 No route to host
热门文章
- 同步 异步 阻塞 非阻塞深入理解
- 迅为I.MX6Q开发板配不同分辨率不同尺寸液晶屏幕
- 【BZOJ3630】[JLOI2014]镜面通道 几何+最小割
- 出现could not find developer disk image解决办法和不受信任的开发者
- Installshield获取安装包版本的系统变量是IFX_PRODUCT_VERSION
- redis文档翻译_key设置过期时间
- jquery div拖动效果示例代码
- 通过 ANE(Adobe Native Extension) 启动Andriod服务 推送消息(二)
- 使用firefox遇到的问题
- [转] 初识Firebug(HTML查看和编辑、Javascript控制台、网络状况监视器)