接觸 Android 以來,一直覺得對 task、affinity 和 launch mode 一知半解,這幾天潛心閱讀 Dev Guide 中的 Activities and Tasks,簡單做下筆記,梳理下這部分的知識。
Android 的一個特色就是 application A 的 activity 可以啟動 application B 的 activity,儘管 A 和 B 是毫無干係的,而在使用者看來,兩個情境緊密聯絡,視覺上二者構成了一個整體。Android 就是把這種誤覺定義為 Task,它既不是 class,也不是 AndroidMainifest.xml 中的一個元素。從表現上看 Task 就像是一個 stack,一個一個的 activity 是構成 stack 的元素,做著入棧 (push) 和出棧 (pop-up)這樣簡單重複性的勞動。
預設的規則總是滿足大多數的應用情境,但是也總會有一些例外打破習以為常的慣例。Task 的預設規則同樣並非牢不可破,修改的方法還是有的。藉助 Intent 中的 flag 和 AndroidMainifest.xml 中 activity 元素的屬性,就可以控制到 Task 裡 Activity 的關聯關係和行為。
在 android.content.Intent 中一共定義了20種不同的 flag,其中和 Task 緊密關聯的有四種:
- FLAG_ACTIVITY_NEW_TASK
- FLAG_ACTIVITY_CLEAR_TOP
- FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
- FLAG_ACTIVITY_SINGLE_TOP
在使用這四個 flag 時,一個 Intent 可以設定一個 flag,也可以選擇若干個進行組合。
預設情況下,通過 startActivity() 啟動一個新的 Activity,新的 Activity 將會和調用者在同一個 stack 中。但是,如果在傳遞給 startActivity() 的 Intent 對象裡包含了 FLAG_ACTION_NEW_TASK,情況將發生變化,–系統將為新的 Activity “尋找”一個不同於調用者的 Task。不過要找的 Task 是不是一定就是 NEW 呢?如果是第一次執行,則這個設想成立,如果說不是,也就是說已經有一個包含此 Activity 的Task
存在,則不會再啟動 Activity。
如果 flag 是 FLAG_ACTIVITY_CLEAR_TOP,同時當前的 Task 裡已經有了這個 Activity,那麼情形又將不一樣。Android 不但不會啟動新的 Activity 執行個體,而且還會將 Task 裡 該 Activity 之上的所有 Activity 一律結束掉,然後將 Intent 發給這個已存在的 Activity。Activity 收到 Intent 之後,可以在 onNewIntent() 裡做下一步的處理,也可以自行結束然後重新建立自己。如果 Activity 在
AndroidMainifest.xml 裡將啟動模式設定成”standrd”,– 預設模式,並且 Intent 裡也沒有設定 FLAG_ACTIVITY_SINGLE_TOP,那麼它將選擇後者。否則,它將選擇前者。FLAG_ACTIVITY_CLEAR_TOP 還可以和 FLAG_ACTION_NEW_TASK 配合使用。
如果 flag 設定的是 FLAG_ACTIVITY_SINGLE_TOP,則意味著如果 Activity 已經是運行在 Task 的 top,則該 Activity 將不會再被啟動。