网上讲解activity的launchmode时,对singletask大部分的说明都是:“singleTask”和”singleInstance”则限制只生成一个实例,并且是task的根元素。
这个的后半句是错的,幸好看到了几篇专门讲解singletask模式的文章。
推荐:http://blog.youkuaiyun.com/luoshengyang/article/details/6714543 这个是老罗的
以及 http://blog.youkuaiyun.com/wdaming1986/article/details/7304191
从singletask讲起,就不得不提到taskaffinity属性。taskaffinity顾名思义,就是描述activity的类型之间的归附关系。
每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。如果一个Activity没有显式的指明该 Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果 Application也没有指明,那么该taskAffinity的值就等于包名。而Task也有自己的affinity属性,它的值等于它的根 Activity的taskAffinity的值。如下:
<activity
android:name="com.yj.testuserfeed.UserFeedOne"
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="UserFeedTwo"
android:launchMode="singleTask"
android:taskAffinity="com.testaffinity" >
</activity>
我的包名是com.yj.testuserfeed;然后在mainactivity中去启动UserFeedTwo这个Activity。
protected void onResume() {
super.onResume();
mName.setText(TAG+"---"+this+"----"+getTaskId()+"---"+isTaskRoot());
}
此时可以看到两个activity位于不同的栈中,121为taskid,true表示为task根元素。
当我把第一个activity的taskaffinity也设置成com.testaffinity时,在第二个activity启动后,显示此activity不为根元素,而且所在的taskid和第一个activity相同。
当把UserFeedOne的taskaffinity缺省,UserFeedTwo的taskaffinity设置为包名,即com.yj.testuserfeed时,两者还是位于同一栈中,说明缺省的taskaffinity为application的包名。
由上可知,如果两个activity的taskaffinity相同时,即使UserFeedTwo设置为singletask,也不会新开一个栈来存放,而是还位于原来的栈中,即使在intent中设置了i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);也不行。
从上面的实验来看,验证了老罗的话:
至此,我们总结一下,设置了"singleTask"启动模式的Activity的特点:
1. 设置了"singleTask"启动模式的Activity,它在启动的时候,会先在系统中查找属性值affinity等于它的属性值taskAffinity的
任务存在;如果存在这样的任务,它就会在这个任务中启动,否则就会在新任务中启动。因此,如果我们想要设置了"singleTask"启动模式的Activity在新的任务中启动,就要为它设置一个独立的taskAffinity属性值。
2. 如果设置了"singleTask"启动模式的Activity不是在新的任务中启动时,它会在已有的任务中查看是否已经存在相应的Activity
实例,如果存在,就会把位于这个Activity实例上面的Activity全部结束掉,即最终这个Activity实例会位于任务的堆栈顶端中。
TaskAffinity和几个launchmode以及Intent.FLAG_ACTIVITY_NEW_TASK等启动模式,这三者之间的关系说起来很复杂,有各种各样的组合,不过其实这些都和AMS中对activity的管理有关。
比如实验的时候遇到了一个有意思的情况,用了三个activity,A为main入口,B为singletask并且未设置taskaffinity,C为singleInstance,每个activity都有三个按钮可以进入其他activity,此时如果是A—>B—>C—>B时,按返回键的顺序为B—>A—>C;说明android的返回键来finish activity时即为出栈的过程,这个就和AMS中的ActivityRecord和mHistory有关了。