Android API Guides 閱讀筆記(6)----Task and Back Stack

Task是當用戶操作時用到的一組Activity的集合,運行中的Activity放在回退棧中存儲(back stack),按執行順序排列。系統會爲每一個運行的應用程序分配一個Task和對應的回退棧,一個系統中可以同時存在多個Task,但是同一時間只能有一個Task顯示在前臺,其他Task將處於後臺,並且其中的Activity都將處於stop狀態,關於Task和Back Stack,需要了解以下幾點:

  • 設備的主屏幕或者菜單(就是通過點擊圖標來啓動一個應用程序的地方)是Task的起點,啓動一個應用程序,此應用程序的Task就來到前臺,如果這個應用程序沒有Task(最近沒有使用過這個應用程序),就會爲此應用程序新建一個Task,如果最近使用過此應用程序(系統會將它的Task保留在後臺),將會重新調用此應用程序的Task

  • 假設有兩個Activity:Activity_A和Activity_B,如果從Activity_A中啓動Activity_B,則Activity_B處於棧頂,Activity_A會保留在棧中,但是處於stop的狀態,系統會保留其UI的狀態,當用戶在Activity_B中按了物理返回鍵退出後,Activity_A就會回到棧頂並恢復其UI狀態,處於resume狀態

  • 當用戶在一個應用程序中持續按返回鍵(在一個Activity中按返回鍵會將其從棧中彈出),直到回到設備主屏幕,也就是所有的Activity都從棧中彈出了,這個應用程序所在的Task也就不存在了

  • 啓動一個應用程序,系統就會自動爲其分配Task和棧,如果同時存在太多的後臺Task,系統由於內存不足會自動清理一部分後臺Task中的Activity,這樣,其狀態就不存在了,也就是當用戶重新回到這個應用程序時,原來的Activity將會重新創建而不是處於resume狀態

  • 由於Android系統允許在一個應用程序的Activity中啓動另一個應用程序的Activity(這在Activity中有筆記),也就是說,一個Activity可能會在多個Task中存在(當多個應用程序都調用這個Activity時),而且是互不關聯 ,擁有各自UI狀態。爲了避免這種情況,就需要管理Task

  • 當用戶按下Home鍵離開Task 時,當前 Activity 停止Task 轉入後臺,系統會保存Task中每個Activity 的狀態。如果用戶以後通過選中啓動該 Task 的圖標來恢復Task,Task 就會回到前臺,棧頂的Activity 會恢復運行.
    如果用戶按下返回鍵,當前Activity 從棧中彈出,並被銷燬.棧中前一個Activity恢復運行.當Activity 被銷燬時,系統不會保留Activity 的狀態.

  • Activity可以在不同的Task中被實例化多次

通過管理Task,可以實現如下功能:

  • 讓應用程序中的某個Activity啓動一個新的Task,而不是放入當前應用程序的Task中

  • 讓Activity啓動時是通過從back stack中調出之前存入過的,而不是重新創建這個Activity並再此將其壓入back stack(避免同一個Activity重複出現在back stack中

  • 在用戶離開當前Task時值保留”根Activity”而back stack中的其他Activity都清空

如何管理Task:

通常有兩種方式來管理一個Activity和它的Task,一種是直接在其對應的清單文件中的< activity >節點下修改相應屬性,另一種是在啓動某個Activity

  • 通過清單文件(AndroidManifest.xml)中的< Activity >節點屬性:

    • taskAffinity:affinities表示Activity對Task的相關性,默認情況下同一個應用程序中的所有Activity都有相同的affinities值,可以在清單文件中的< activity >節點中修改taskAffinities值,通常在兩種情況下會使用到affinities:

      • 當一個Intent通過FLAG_ACTIVITY_NEW TASK標籤啓動一個Activity時
        默認情況下,一個新的Activity將被放入調用startActivity()的Activity 所在Task 中,且壓入調用者所在的Back Stack 頂棧

      • 當一個Activity在其< activity >標籤添加屬性allowTaskReparenting並賦值爲true時
        在這種情況下,當某個Task 進入前臺時,Activity 的affinity 值又與其相同,則它可以從啓動時的Task 移入這個Task 中.

    • launchMode

      • standard(默認模式):系統將會在當前應用程序的Task中創建一個新的實例,並使Intent指向它,這種模式的Activity可以實例化多次,每一個實例可以屬於不同的Task(從不同的Activity中使用Intent指向它),並且,一個Task可以有多個相同的Activity實例(原有的Activity仍然按順序存在棧中)

      • singleTop(棧頂複用模式):如果當前應用程序的Task中已經存在這個Activity的實例了,當通過Intent啓動這個Activity時,會調用Activity中的onNewIntent()(而不是onCreate()方法,因爲onCreate()方法是在Activity新建的時候調用,而這裏不是新建)假設Task 的 Back Stack 中包含了根Activity A 和 Activities B、C、D(順序是 A-B-C-D; D在棧頂. 這時候傳過來的是啓動D的intent,如果D的啓動模式是默認的”standard”,則會啓動一個新的實例,棧的內容就會變爲 A-B-C-D-D.但是,如果 D 的啓動模式是 “singleTop”,則已有的D的實例會通過onNewIntent():接收這個 intent,因爲該實例位於棧頂——棧中內容仍然維持 A-B-C-D 不變.當然,如果 intent 是要啓動 B 的,則 B 的一個新實例還是會加入棧中,即使 B 的啓動模式是”singleTop”也是如此.棧中內容爲A-B-C-D-B

      • singleTask(棧內複用模式):一般作爲應用程序主Activity,系統將創建一個新的Task,這個Activity是第一個放入新的Task,如果其他Task(除當前應用程序以外的Task)中已經有實例存在,則會調用其onNewIntent(),而不是再創建一個新的Activity,此Activity在同一時刻只能有一個實例存在,雖然啓動了一個新的Activity,但是通過返回鍵仍然可以返回之前的Activity

      • singleInstance(單實例模式):大致和singleTask模式相同,唯一的不同是,系統不會在當前Activity所在的Task中啓動其他的Activity,也就是說這個Activity總是單獨的處在一個Task中(這個Task不允許其他的Activity存在),從這個Activity中啓動的Activity也會被分離到其他Task

    • alwaysRetainTaskState:如果在跟Activity(通常是程序入口Activity)中將此屬性值設爲true,則即使用戶離開一個Task很長時間,系統也不會清除掉這個Task中的任何Activity,所有的Activity都會保留

    • cleanTaskOnLaunch:這個屬性是上面alwaysRetainTaskState的對立面,也就是說,如果將此屬性值設爲true,則無論用戶離開多久,系統都會將棧中的所有Activity清理掉(當然,仍然會保留跟Activity),清理回退棧的內容在下面

    • finishOnTaskLaunch:此屬性類似cleanTaskOnLaunch:但是,它只對一個Activity有效(也就是某個在節點設置了此屬性爲true的Activity)

  • 通過調用startActivity()時用到的Intent中的flag:

    • FLAG_ACTIVITY_NEW _TASK:和singleTask模式相同,在新的Task中啓動目標Activity,如果那個Activity之前已經存在了,它將會回到前臺並恢復之前的狀態,並調用其onNewIntent()方法

    • FLAG_ACTIVITY_CLEAN_TOP:和singleTop模式相同,如果要啓動的Activity是當前的Activity(位於棧頂),則會調用當前Activity中的onNewIntent()方法,不會創建新的實例

    • FLAG_ACTIVITY_SINGLE_TOP:如果要啓動的Activity已經在當前Task中運行(不一定處於棧頂),將不會創建一個新的實例,而是會將這個Activity之上的所有其他Activity銷燬,然後將此Activity恢復到棧頂,調用其onNewIntent()方法

注意:如果 Activity A 啓動了Activity B,則 Activity B 可以在 manifest 中定義它如何與當之前的Task 關聯(如果存在的話),Activity A 也可以要求 Activity B 與當前 task 的關聯關係.如果兩個Activity都有定義,則 Activity A 的請求(intent 中定義)會比Activity B 的定義(在 manifest 中)優先.

清理回退棧(back stack):

如果用戶長時間離開一個Task,則系統將會清理掉這個Task中的其他Activity,只保留棧底的”根Activity“(一般爲程序入口Activity),當用戶重新啓動這個Task時,只有根Activity會恢復(因爲棧中只有這一個Activity)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章