1. 程式人生 > >"singleTask"模式 切換到新的棧中

"singleTask"模式 切換到新的棧中

能夠 class blank 運行 部分 gem launcher2 1.0 nac

本文截取了網絡資源的結論部分 對singletask 啟動模式做筆記記錄。


盡管SubActivity的launchMode被設置為"singleTask"模式,可是它並不像官方文檔描寫敘述的一樣:The system creates a new task and instantiates the activity at the root of the new task。而是在跟它有同樣taskAffinity的任務中啟動。而且位於這個任務的堆棧頂端,於是。前面那個圖中,就會出現一個帶著"singleTask"標簽的箭頭指向一個任務堆棧頂端的Activity Y了。

那麽,我們有沒有辦法讓一個"singleTask"的Activity在新的任務中啟動呢?答案是肯定的。從上面的代碼分析中,僅僅要我們可以進入函數startActivityUncheckedLocked的這個if語句中: [java]
view plaincopy
  1. if (r.resultTo == null && !addingToTask
  2. && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
  3. // todo: should do better management of integers.
  4. mService.mCurTask++;
  5. if (mService.mCurTask <= 0) {
  6. mService.mCurTask = 1;
  7. }
  8. r.task = new TaskRecord(mService.mCurTask, r.info, intent,
  9. (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
  10. if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
  11. + " in new task " + r.task);
  12. newTask = true;
  13. if (mMainStack) {
  14. mService.addRecentTaskLocked(r.task);
  15. }
  16. }
那麽,這個即將要啟動的Activity就會在新的任務中啟動了。進入這個if語句須要滿足三個條件,r.resultTo為null,launchFlags的Intent.FLAG_ACTIVITY_NEW_TASK位為1。而且addingToTask值為false。從上面的分析中能夠看到。當即將要啟動的Activity的launchMode為"singleTask",而且調用startActivity時不要求返回要啟動的Activity的運行結果時,前面兩個條件能夠滿足。要滿足第三個條件,僅僅要當前系統不存在affinity屬性值等於即將要啟動的Activity的taskAffinity屬性值的任務就能夠了。


我們能夠略微改動一下上面的AndroidManifest.xml配置文件來做一下這個實驗:

[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?

    >

  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="shy.luo.task"
  4. android:versionCode="1"
  5. android:versionName="1.0">
  6. <application android:icon="@drawable/icon" android:label="@string/app_name">
  7. <activity android:name=".MainActivity"
  8. android:label="@string/app_name"
  9. android:taskAffinity="shy.luo.task.main.activity">
  10. <intent-filter>
  11. <action android:name="android.intent.action.MAIN" />
  12. <category android:name="android.intent.category.LAUNCHER" />
  13. </intent-filter>
  14. </activity>
  15. <activity android:name=".SubActivity"
  16. android:label="@string/sub_activity"
  17. android:launchMode="singleTask"
  18. android:taskAffinity="shy.luo.task.sub.activity">
  19. <intent-filter>
  20. <action android:name="shy.luo.task.subactivity"/>
  21. <category android:name="android.intent.category.DEFAULT"/>
  22. </intent-filter>
  23. </activity>
  24. </application>
  25. </manifest>
註意,這裏我們設置MainActivity的taskAffinity屬性值為"shy.luo.task.main.activity",設置SubActivity的taskAffinity屬性值為"shy.luo.task.sub.activity"。

又一次編譯一下程序。在模擬器上把這個應用程序再次跑起來。用“adb shell dumpsys activity”命令再來查看一下系統執行的的任務,就會看到:

[html] view plaincopy
  1. Running activities (most recent first):
  2. TaskRecord{4069c020 #4 A shy.luo.task.sub.activity}
  3. Run #2: HistoryRecord{40725040 shy.luo.task/.SubActivity}
  4. TaskRecord{40695220 #3 A shy.luo.task.main.activity}
  5. Run #1: HistoryRecord{406b26b8 shy.luo.task/.MainActivity}
  6. TaskRecord{40599c90 #2 A com.android.launcher}
  7. Run #0: HistoryRecord{40646628 com.android.launcher/com.android.launcher2.Launcher}
這裏就能夠看到,SubActivity和MainActivity就分別執行在不同的任務中了。


至此,我們總結一下,設置了"singleTask"啟動模式的Activity的特點:

1. 設置了"singleTask"啟動模式的Activity,它在啟動的時候,會先在系統中查找屬性值affinity等於它的屬性值taskAffinity的任務存在。假設存在這種任務,它就會在這個任務中啟動。否則就會在新任務中啟動。因此。假設我們想要設置了"singleTask"啟動模式的Activity在新的任務中啟動。就要為它設置一個獨立的taskAffinity屬性值。

2. 假設設置了"singleTask"啟動模式的Activity不是在新的任務中啟動時,它會在已有的任務中查看是否已經存在對應的Activity實例。假設存在,就會把位於這個Activity實例上面的Activity所有結束掉,即終於這個Activity實例會位於任務的堆棧頂端中。

&quot;singleTask&quot;模式 切換到新的棧中