[Android] Android 任務棧 【轉載】

 

做者:三十二蟬
連接:https://www.jianshu.com/p/59ab98d7850e
來源:簡書
簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。html

 

任務與任務棧

任務是指在執行特定做業時與用戶交互的一系列 Activity。 這些 Activity 按照各自的打開順序排列在堆棧(即返回棧)中。設備主屏幕是大多數任務的起點。當用戶觸摸應用啓動器中的圖標(或主屏幕上的快捷方式)時,該應用的任務將出如今前臺。 若是應用不存在任務(應用最近不曾使用),則會建立一個新任務,而且該應用的「主」Activity 將做爲堆棧中的根 Activity 打開。
當前 Activity 啓動另外一個 Activity 時,該新 Activity 會被推送到堆棧頂部,成爲焦點所在。 前一個 Activity 仍保留在堆棧中,可是處於中止狀態。Activity 中止時,系統會保持其用戶界面的當前狀態。 用戶按「返回」按鈕時,當前 Activity 會從堆棧頂部彈出(Activity 被銷燬),而前一個 Activity 恢復執行(恢復其 UI 的前一狀態)。 堆棧中的 Activity 永遠不會從新排列,僅推入和彈出堆棧:由當前 Activity 啓動時推入堆棧;用戶使用「返回」按鈕退出時彈出堆棧。 所以,返回棧以「後進先出」對象結構運行。
android

 
Activity返回棧

任務是一個有機總體,當用戶開始新任務或經過 「主頁」按鈕轉到主屏幕時,能夠移動到「後臺」。 儘管在後臺時,該任務中的全部 Activity 所有中止,可是任務的返回棧仍舊不變,也就是說,當另外一個任務發生時,該任務僅僅失去焦點而已,如圖 2 中所示。而後,任務能夠返回到「前臺」,用戶就可以回到離開時的狀態。 例如,假設當前任務(任務 A)的堆棧中有三個 Activity,即當前 Activity 下方還有兩個 Activity。 用戶先按 「主頁」按鈕,而後從應用啓動器啓動新應用。 顯示主屏幕時,任務 A 進入後臺。新應用啓動時,系統會使用本身的 Activity 堆棧爲該應用啓動一個任務(任務 B)。與該應用交互以後,用戶再次返回主屏幕並選擇最初啓動任務 A 的應用。如今,任務 A 出如今前臺,其堆棧中的全部三個 Activity 保持不變,而位於堆棧頂部的 Activity 則會恢復執行。 此時,用戶還能夠經過轉到主屏幕並選擇啓動該任務的應用圖標(或者,經過從 概覽屏幕選擇該應用的任務)切換回任務 B。這是 Android 系統中的一個多任務示例。
 
兩個任務:任務 B 在前臺接收用戶交互,而任務 A 則在後臺等待恢復。

因爲返回棧中的 Activity 永遠不會從新排列,所以若是應用容許用戶從多個 Activity 中啓動特定 Activity,則會建立該 Activity 的新實例並推入堆棧中(而不是將 Activity 的任一先前實例置於頂部)。 所以,應用中的一個 Activity 可能會屢次實例化(即便 Activity 來自不一樣的任務),如圖 3 所示。所以,若是用戶使用 「返回」按鈕向後導航,則會按 Activity 每一個實例的打開順序顯示這些實例(每一個實例的 UI 狀態各不相同)。 可是,若是您不但願 Activity 屢次實例化,則可修改此行爲。 具體操做方法將在後面的 管理任務部分中討論。
 
一個 Activity 將屢次實例化

 

Activity和任務的默認行爲總結

  • 當 Activity A 啓動 Activity B 時,Activity A 將會中止,但系統會保留其狀態(例如,滾動位置和已輸入表單中的文本)。若是用戶在處於 Activity B 時按「返回」按鈕,則 Activity A 將恢復其狀態,繼續執行。
  • 用戶經過按「主頁」按鈕離開任務時,當前 Activity 將中止且其任務會進入後臺。 系統將保留任務中每一個 Activity 的狀態。若是用戶稍後經過選擇開始任務的啓動器圖標來恢復任務,則任務將出如今前臺並恢復執行堆棧頂部的 Activity。
  • 若是用戶按「返回」按鈕,則當前 Activity 會從堆棧彈出並被銷燬。 堆棧中的前一個 Activity 恢復執行。銷燬 Activity 時,系統不會保留該 Activity 的狀態。
  • 即便來自其餘任務,Activity 也能夠屢次實例化。

上述文字摘自 Android開發者官網app

改變Activity、返回任務棧默認行爲的相關屬性

默認行爲的場景:當前的task包含4個activity–當前activity下面有3個activity。當用戶按下HOME鍵返回到程序啓動器(application launcher)後,選擇了一個新的應用程序(事實上是一個新的task),當前的task就被轉移到後臺,新的task中的根activity將被顯示在屏幕上。過了一段時間,用戶按返回鍵回到了程序啓動器界面,選擇了以前運行的程序(以前的task)。那個task,仍然包含着4個activity。當用戶再次按下返回鍵時,屏幕不會顯示以前留下的那個activity(以前的task的根activity),而顯示當前activity從task棧中移出後棧頂的那個activity。ide

能夠改變任務棧默認行爲的Intent標示

  • FLAG_ACTIVITY_NEW_TASK:
    當傳遞給startActivity()的Intent對象包含FLAG_ACTIVITY_NEW_TASK標記時,系統會爲須要啓動的activity尋找與當前activity不一樣的task。若是要啓動的activity的affinity屬性與當前全部的task的affinity屬性都不相同,系統會新建一個帶那個affinity屬性的task,並將要啓動的activity壓到新建的task棧中;不然將activity壓入那個affinity屬性相同的棧中。
  • FLAG_ACTIVITY_CLEAR_TOP:
    若是intent對象包含FLAG_ACTIVITY_CLEAR_TOP標記,當目標task中已存在與接收該intent對象的activity類型相同的activity實例存在時,全部位於該activity對象上面的activity將被清空,這樣接收該intent的activity就位於棧頂,能夠響應到來的intent對象。若是目標activity的運行模式爲standard,則目標activtiy也會被清空。由於當運行模式爲standard時,總會建立新的activity對象來接收到來的intent對象。
  • FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:
  • FLAG_ACTIVITY_SINGLE_TOP:

能夠改變任務棧默認行爲的Activity屬性

  • taskAffinity:
    默認狀況下,一個應用程序中的全部activity都有一個affinity–這讓它們屬於同一個task。然而,每一個activity能夠經過<activity>中的taskAffinity屬性設置單獨的affinity。不一樣應用程序中的activity能夠共享同一個affinity,同一個應用程序中的不一樣activity也能夠設置成不一樣的affinity。affinity屬性在2種狀況下起做用:當啓動activity的Intent對象包含FLAG_ACTIVITY_NEW_TASK標記,或當activity的allowTaskReparenting被設置成true。
  • launchMode:
    如下假設位於task1中的activity1啓動activity2:
模式\分類 包容activity2的task 一個activity是否容許有多個實例 activity是否容許有其它activity共存於一個task 對於新的intent,是否老是實例化activity對象
standard 若是不包含FLAG_ACTIVITY_NEW_TASK標記,則activity2放入task1,不然按前面講述的規則爲activity2選擇task 可被屢次實例化,同一個task的不一樣的實例可位於不一樣的task中,每一個task也可包含多個實例 容許 是的。當接收到新的intent時,老是會生成新的activity對象。
singleTop 同standard 同standard 容許 已存在的activity對象,若是位於目標task的棧頂,則該activity被重用,若是它不位於棧頂,則會實例化新的activity對象
singleTask 將activity2放到task1棧頂 不能有多個實例。因爲該模式下添加後的activity老是位於棧頂,因此actvity在同一個設備(若是app只有一個任務棧)裏至多隻有一個實例 容許。singleTask模式下,添加後的activity老是位於棧頂位置。目標activity實例已存在時,若是該實例恰好位於task棧中,則接收intent,不然到來的intent將會被丟棄,但該能夠響應該intent的那個activity所在的task將會被移到前臺(若其餘應用啓動該Activity;若是不存在,則新建Task;若是已經存在於後臺Task中,那麼後臺Task會被切換到前臺)  
singleInstance 同singleTask 同singleTask 不容許與其它activity共存於一個task。若是activity1的運行在該模式下,則activity2必定與activity1位於不一樣的task  
  • allowTaskReparenting:
    若是一個activity的allowTaskReparenting屬性爲true,那麼它能夠從一個task(TASK1)移到另一個有相同affinity的task(TASK2)中(TASK2帶到前臺時)。
    若是一個.apk文件從用戶角度來看包含了多個「應用程序」,你可能須要對那些activity賦不一樣的affinity值。
  • clearTaskOnLaunch:
    若是棧底activity的這個屬性被設置爲true,一旦用戶離開task,則task棧中的activity將被清空到只剩下棧底activity。這種狀況恰好與alwaysRetainTaskState相反。即便用戶只是短暫地離開,task也會返回到初始狀態(只剩下棧底acitivty)。
  • alwaysRetainTaskState:
    默認清空棧的行爲:當用戶長時間離開task(當前task被轉移到後臺)時,系統會清除task中棧底activity外的全部activity。這樣,當用戶返回到task時,只留下那個task最初始的activity了。
    若是棧底activity的這個屬性被設置爲true,剛剛描述的狀況就不會發生。task中的全部activity將被長時間保存。
  • finishOnTaskLaunch: 這個屬性與clearTaskOnLaunch類似,但它只對單獨的activity操做,而不是整個task。它能夠結束任何activity,包括棧底的activity。當它設置爲true時,當前的activity只在當前會話期間做爲task的一部分存在,當用戶退出activity再返回時,它將不存在。
相關文章
相關標籤/搜索