android Activity launch mode 一个实例 singleTask
参考:http://blog.csdn.net/ljz2009y/article/details/26621815
一个应用 三个页面 第二个页面设置为 singlTask
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jg.zhang.androidtasktest" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name"> <activity android:label="@string/app_name" android:name="com.jg.zhang.androidtasktest.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!--android:taskAffinity="com.jg.zhang.androidtasktest.second" android:alwaysRetainTaskState="true" android:allowBackup="true" --> <activity android:name="com.jg.zhang.androidtasktest.SecondActivity" android:launchMode="singleTask"> <intent-filter > <action android:name="com.jg.zhang.androidtasktest.SecondActivity"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> <activity android:name="com.jg.zhang.androidtasktest.ThirdActivity" android:label="@string/app_name" > </activity> </application> </manifest>
在命令行中执行以下命令 adb shell dumpsys activity , 有以下输出:
TaskRecord{412ded08 #8 A com.jg.zhang.androidtasktest}
Run #2: ActivityRecord{412c91e8 com.jg.zhang.androidtasktest/.SecondActivity}
Run #1: ActivityRecord{412c08a0 com.jg.zhang.androidtasktest/.MainActivity}
且点击MainActivity界面中的按钮,开启SecondActivity。在该示例中SecondActivity的启动模式为singleTask。按照官方文档的说法,SecondActivity会在一个新的任务中开启。但是查看打印出的log,发现MainActivity和SecondActivity所在的任务的Id相同。
所以,和官方文档表述的不同,MainActivity和SecondActivity是启动在同一个任务中的。其实,把启动模式设置为singleTask,framework在启动该activity时只会把它标示为可在一个新任务中启动,至于是否在一个新任务中启动,还要受其他条件的限制。现在在SecondActivity增加一个taskAffinity属性
<activity android:name="com.jg.zhang.androidtasktest.SecondActivity" android:launchMode="singleTask" android:taskAffinity="com.jg.zhang.androidtasktest.second"> <intent-filter > <action android:name="com.jg.zhang.androidtasktest.SecondActivity"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> lt;/activity>
重新运行该示例
在命令行中执行adb shell dumpsys activity命令,有以下输出:
TaskRecord{411e6a88 #6 A com.jg.zhang.androidtasktest.second}
Run #3: ActivityRecord{411c8ea0 com.jg.zhang.androidtasktest/.ThirdActivity}
Run #2: ActivityRecord{412bc870 com.jg.zhang.androidtasktest/.SecondActivity}
TaskRecord{412ece18 #5 A com.jg.zhang.androidtasktest}
Run #1: ActivityRecord{412924c0 com.jg.zhang.androidtasktest/.MainActivity}
由此可见,MainActivity和SecondActivity运行在不同的任务中了,并且被SecondActivity启动的ThirdActivity和SecondActivity运行在同一个任务中。
taskAffinity可以影响当activity以FLAG_ACTIVITY_NEW_TASK标志启动时,它会被启动到哪个任务中。这句话的意思是,当新启动的activity(SecondActivity)是以FLAG_ACTIVITY_NEW_TASK标志启动时(可以认为FLAG_ACTIVITY_NEW_TASK和singleTask作用相同,当启动模式为singleTask时,framework会将它的启动标志设为FLAG_ACTIVITY_NEW_TASK),framework会检索是否已经存在了一个affinity为com.jg.zhang.androidtasktest.second的任务(即一个TaskRecord对象)
- 如果存在这样的一个任务,则检查在这个任务中是否已经有了一个SecondActivity的实例,
- 如果已经存在一个SecondActivity的实例,则会重用这个任务和任务中的SecondActivity实例,将这个任务调到前台,清除位于SecondActivity上面的所有Activity,显示SecondActivity,并调用SecondActivity的onNewIntent();
- 如果不存在一个SecondActivity的实例,会在这个任务中创建SecondActivity的实例,并调用onCreate()方法
- 如果不存在这样的一个任务,会创建一个新的affinity为com.jg.zhang.androidtasktest.second的任务,并且将SecondActivity启动到这个新的任务中
上面讨论的是设置taskAffinity属性的情况,如果SecondActivity只设置启动模式为singleTask,而不设置taskAffinity,即三个Activity的taskAffinity相同,都为应用的包名,那么SecondActivity是不会开启一个新任务的,framework中的判定过程如下:
- 在MainActivity启动SecondActivity时,发现启动模式为singleTask,那么设定他的启动标志为FLAG_ACTIVITY_NEW_TASK
- 然后获得SecondActivity的taskAffinity,即为包名com.jg.zhang.androidtasktest
- 检查是否已经存在一个affinity为com.jg.zhang.androidtasktest的任务,这个任务是存在的,就是MainActivity所在的任务,这个任务是在启动MainActivity时开启的
- 既然已经存在这个任务,就检索在这个任务中是否存在一个SecondActivity的实例,发现不存在
- 在这个已有的任务中启动一个SecondActivity的实例
为了作一个清楚的比较,列出SecondActivity启动模式设为singleTask,并且taskAffinity设为com.jg.zhang.androidtasktest.second时的启动过程
- 在MainActivity启动SecondActivity时,发现启动模式为singleTask,那么设定他的启动标志为FLAG_ACTIVITY_NEW_TASK
- 然后获得SecondActivity的taskAffinity,即com.jg.zhang.androidtasktest.second
- 检查是否已经存在一个affinity为com.jg.zhang.androidtasktest.second的任务,这个任务是不存在的
- 创建一个新的affinity为com.jg.zhang.androidtasktest.second的任务,并且将SecondActivity启动到这个新的任务中