转载:http://www.byysoo.com/a/webqianduan/2011/0911/11526.html
Activity的归属,也就是Activity应当在哪个Task中,Activity与Task的吸附关系。我们知道,一般景象下在同一个应用中,启动的Activity都在同一个Task中,它们在该Task中度过本身的生命周期,这些Activity是从一而终的好榜样。
魔难是人生的教员。经由过程魔难,走向欢欣。 那么为什么我们创建的Activity会进入这个Task中?它们会转到其它的Task中吗?若是转到其它的Task中,它们会到什么样的Task中去?
解决这些题目的关键,在于每个Activity的taskAffinity属性。
每个Activity都有taskAffinity属性,这个属性指出了它欲望进入的Task。若是一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就便是Application指明的taskAffinity,若是Application也没有指明,那么该taskAffinity的值就便是包名。而Task也有本身的affinity属性,它的值便是它的根Activity的taskAffinity的值。
一开端,创建的Activity都邑在创建它的Task中,并且大项目组都在这里度过了它的全部生命。然而有一些景象,创建的Activity会被分派其它的Task中去,有的甚至,底本在一个Task中,之后呈现了转移。我们起首解析一下android文档给我们介绍的两种景象。
第一种景象。若是该Activity的allowTaskReparenting设置为true,它进入后台,当一个和它有雷同affinity的Task进入前台时,它会从头宿主,进入到该前台的task中。
我们验证一下这种景象。
Application Activity taskAffinity allowTaskReparenting
application1 Activity1 com.winuxxan.affinity true
application2 Activity2 com.winuxxan.affinity false
我们创建两个工程,application1和application2,分别含有Activity1和Activity2,它们的taskAffinity雷同,Activity1的allowTaskReparenting为true。
起首,我们启动application1,加载Activity1,然后按Home键,使该task(假设为task1)进入后台。然后启动application2,默认加载Activity2。
我们看到了什么现象?没错,底本应当是显示Activity2,然则我们却看到了Activity1。实际上Activity2也被加载了,只是Activity1从头宿主,所以看到了Activity1。
第二种景象。若是加载某个Activity的intent,Flag被设置成FLAG_ACTIVITY_NEW_TASK时,它会起首搜检是否存在与本身taskAffinity雷同的Task,若是存在,那么它会直接宿主到该Task中,若是不存在则从头创建Task。
我们来做一个测试。
我们起首写一个应用,它有两个Activity(Activity1和Activity2),AndroidManifest.xml如下:
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Activity1"
android:taskAffinity="com.winuxxan.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);
}
}
然后,我们再写一个应用MyActivity,它包含一个Activity(MyActivity),AndroidManifest.xml如下:
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MyActivity"
android:taskAffinity="com.winuxxan.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。然后按返回键。
我们发明,我们进入Activity的次序为Activity2->Activity1,而返回时次序为Activity1->MyActivity。这就说了然一个题目,Activity1在启动时,从头宿主到了MyActivity地点的Task中去了。
以上是验证了文档中提出的两种TaskAffinity的用法。
下面就是见证古迹的时刻,同道们,不要眨眼!
我们如今将上一文中的launchMode和本文讲的taskAffinity连络起来。
起首是singleTask加载模式与taskAffinity的连络。
我们还是用上一文中的singleTask的代码,这里就不在列出来了,请读者本身查阅上一文。独一不合的就是,我们为MyActivity和Activity1设置成雷同的taskAffinity,从头履行上文的测试。
我们发明测试成果令我们惊奇:从同一应用法度启动singleTask和不合应用法度启动的成果完全与上文讲的相反!
我们经过思虑,就可以把从同一应用法度履行和从不合应用法度履行另种体式格式同一路来,获得一个结论:
当一个应用法度加载一个singleTask模式的Activity时,起首该Activity会搜检是否存在与它的taskAffinity雷同的Task。
1、若是存在,那么搜检是否实例化,若是已经实例化,那么烧毁在该Activity以上的Activity并调用onNewIntent。若是没有实例化,那么该Activity实例化并入栈。
2、若是不存在,那么就从头创建Task,并入栈。
用一个流程来默示:
然后我们来检测singleInstance模式融入taskAffinity时的景象,我们也是用上文中测试singleInstance的例子,在此不列出,读者翻阅前文查阅。独一不合的是,我们将MyActivity和Activity2设置成雷同的taskAffinity。
我们发明测试成果也有必然的进出,就是,当从singleInstance中启动Activity时,并没用从头创建一个Task,而是进入了和它具有雷同affinity的MyActivity地点的Task。
于是,我们也能获得以下结论:
1、当一个应用法度加载一个singleInstance模式的Activity时,若是该Activity没有被实例化,那么就从头创建一个Task,并入栈,若是已经被实例化,那么就调用该Activity的onNewIntent;
2、singleInstance的Activity地点的Task不容许存在其他Activity,任何从该Activity加载的其它Actiivty(假设为Activity2)都邑被放入其它的Task中,若是存在与Activity2雷同affinity的Task,则在该Task内创建Activity2。若是不存在,则从头生成新的Task并入栈。