)Android下的任務和Activity棧

來源:互聯網
上載者:User
就像前面提到的,一個activity可以啟動另一個,包括那些定義在不同應用程式中的。假設,例如,你想讓使用者顯示一些地方的街道地圖。已經有一個activity可以做這個事,所以你的activity所要做的就是將行為對象和需要的資訊放在一起,並將它們傳遞給startActivity()。 地圖查看器將顯示這個地圖。當使用者按下後退按鈕時,你的activity又重新顯示在螢幕上了。
對使用者來說,這個地圖查看器看起來就像是你的應用程式的一部分,即使它定義在另外的應用程式中並運行在那個程式的進程中。Android 通過保持所有的activity在同一個任務中來保持使用者體驗。簡單的的說,任務就是使用者所體驗到的“應用程式”。它是一組相關的activity,分配到一個棧中。棧中的根activity,是任務的開始——一般來說,它是使用者組應用程式載入器中選擇的activity。在棧頂的activity正是當前正在啟動並執行——集中處理使用者動作的那個。當一個activity啟動了另外一個,這個新的activity將壓入棧中,它將成為正在運行中的 activity。前一個activity保留在棧中。當使用者按下後退按鍵,當前的這個activity將中棧中彈出,而前面的那個activity恢複成運行中狀態。
棧包含了對象,如果一個棧有多於一個相同的Activity的子類的執行個體開啟——比如,多個地圖查看器——這個棧分別擁有每個執行個體的入口。棧中的activity不能重新排列,只能壓入和彈出。
任務是一些activity組成的棧,不是資訊清單檔中的類或元素。所以沒有辦法在獨立於它包含的activity的條件下,設定它的值。任務的值作為一個整體設定在根activity中。例如,下一節將討論“任務的親和性”;這個值是從根activity親和性中讀取出來的。
一個任務中的所有activity一起作為一個單元。整個任務(整個activity棧)可以移動到前台或者後台.假設,例如,當前的任務有四個 activity在棧中——三個在當前的activity之下。使用者按下了HOME鍵,進入了應用程式載入器,選擇了一個新的程式(實際上,是一個新的任務)。當前的任務進入了後台,新任務的根activity顯示出來。然後,過了一會,使用者退回到主介面,又重新選擇了前一個應用程式(前一個任務),棧中有四個activity的那個任務,現在出現在了前台。當使用者按下BACK按鍵,螢幕就不會再顯示使用者剛剛離開的那個activity,而是刪除棧頂的 activity,同任務中的前一個activity將被顯示出來。
剛才說明的那些行為,是activity和任務的預設行為。但是有也辦法修改它的所有方面。activity和任務的關聯,activity在任務中的行為,受控於啟動activity的行為對象的標誌位和資訊清單檔中的<activity> 元素的屬性的互相作用。要求者和相應著都要說明發生了什麼。

在這裡,主要的行為標誌為是:

FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
FLAG_ACTIVITY_SINGLE_TOP

主要的<activity> 屬性是:

taskAffinity
launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch

下面一節將說明這些標誌和屬性都有什麼用,他們之間怎麼互相影響,應該用什麼樣的方案來控制它們的使用。

親和性和新任務

預設情況下,應用程式中的所有activity,都有一個對於其它activity的親和性—這是一個對於同一個任務中的其他activity的優先權,然後,通過 <activity>元素的 taskAffinity 屬性可以可以分別為每一個activity設定親和性。不同應用程式定義的activity可以共用同一個親和性,或者同一個應用程式定義的 activity可以指定不同的親和性。親和性在兩種情況下發揮作用:當行為對象啟動了一個包含 FLAG_ACTIVITY_NEW_TASK標誌的activity,和當一個activity的allowTaskReparenting 屬性設定為“true”。

FLAG_ACTIVITY_NEW_TASK 標誌

正如前面描述的,一個新的activity,預設情況下,被載入進調用startActivity()方法的activity對象所在的那個任務中。它被壓入和調用者所在的同一個棧中,但是,如果行為對象在調用startActivity()方法時傳遞了FLAG_ACTIVITY_NEW_TASK標記,系統將用一個不同的任務來容納這個新的activity。通常,就像這個標記的名字所代表的。它是一個新任務,但是,它不必非要這樣。如果已經存在一個和這個activity親和性相同的任務,這個activity就會載入到那個任務中,如果不是的話,才會啟動新任務。

allowTaskReparenting 屬性

如果activity的allowTaskReparenting 屬性設定為“true”,它就能從他啟動時所在的任務移動到另一個出現在前台的任務。例如,假設有一個activity可以根據選擇的城市包括天氣情況,它作為一個旅行應用程式的一部分。它和同一個應用程式中的其他activity有同樣的親和性(預設的親和性)並且允許重組。你的一個activity開啟了天氣報告器,所以它屬於同一個任務中的這個activity,然而,當旅行應用程式開始運行時,天氣報告器將被重新分配並顯示到那個任務中。

啟動模式

有4中不同的啟動模式可以分配給 <activity> 元素的 launchMode 屬性。

"standard" (預設的模式)
"singleTop "
"singleTask"
"singleInstance"

這些模式主要區別在以下四點:

哪個任務存放著activity,用來對行為進行響應。 對“standard ”和“singleTop ”模式來說,這個任務是產生行為(並且調用startActivity() )的那個——除非行為對象包含了 FLAG_ACTIVITY_NEW_TASK 標記。在這種情況下,像前面那節Affinities and new tasks 描述的一樣,將會選擇一個不同的任務。
它們是否可以有多個執行個體。 "standard "和“singleTop ”類型的activity可以被執行個體化多次。它們可以屬於多個任務,一個特定的任務也可以擁有同一個activity的多個執行個體。
作為比較"singleTask "和"singleInstance "類型的activity只限定有一個執行個體。因為這些activity是任務的根。這個限制意味著,在裝置上不能同時有超過一個任務的執行個體。
是否能有其他的activity在它所在的任務中。"singleInstance " 類型的activity是它所在任務中唯一的activity。如果它啟動了其他的activity,不管那個activity的啟動模式如何,它都會載入到一個不同的任務中——好像行為對象中的FLAG_ACTIVITY_NEW_TASK 標記。在其他的方面,"singleInstance "和"singleTask "模式是相同的。
其他三種模式運行任務中有多個activity。"singleTask "總是任務中的根activity,但是它可以啟動其他的activity並分配到它所在的任務中。"standard "和"singleTop "類型的activity可以出現在任務中的任何地方。
是否啟動一個新的執行個體來處理一個新的行為。 對預設的"standard "模式來說,對於每一個行為都會建立一個新的執行個體來響應。每個執行個體只處理一個行為。對於"singleTop "模式,如果一個已經存在的執行個體位於目標任務activity棧的棧頂,那麼他將被重用來處理這個行為。如果它不在棧頂,它將不會被重用,而是為行為建立一個新的執行個體,並壓入棧中。

例如,假設,一個任務的activity棧由根activity A和 B,C,D從上到下按這樣的順序組成,所以這個棧就是A-B-C-D。一個行為指向類型為D的activity。如果D是預設的"standard "載入模式,一個新的執行個體會被啟動,棧現在就是這樣A-B-C-D-D。但是,如果D的載入模式是"singleTop ",已經存在的執行個體會用來處理這個行為(因為它在棧的頂端)並且棧中還應該是A-B-C-D。
在前面提到,"singleTask "和"singleInstance "類型的activity最多隻有一個執行個體,所以他們的執行個體應該會處理每個新的行為。"singleInstance "類型的activity總是在棧的頂端(因為他是任務中唯一的一個activity),所以總是能夠適當的處理行為。然而,"singleTask "類型的activity也許會有其他的activity在它的上面。如果是這樣的話,那就不能處理這個行為,這個行為被丟棄。(即使這個行為被丟棄了,它的到來也會導致那些應該保留不變任務顯示到前台來)。

當一個activity被要求處理一個新的行為時,行為對象會通過調用activity的 onNewIntent() 方法傳遞進來(最初啟動activity的行為可以通過調用getIntent() 方法獲得)。

注意,當建立一個新的activity執行個體來處理一個新的行為時,使用者總是能夠通過按下BACK按鍵退回到前面的狀態(前一個activity)。但是當一個已經存在的activity執行個體處理一個新的行為時,使用者不能通過按下BACK按鍵退回到前面的狀態。

更多關於載入模式的內容,請看關於 <activity> 的描述。

清理棧

如果使用者離開一個任務很長時間。系統將清除除了根activity之外的所有activity。當使用者重新回到任務中時,像是使用者離開了它,除了只有最初的activity還在。這個理念是這樣的,過了一段時間,使用者很可能放棄之前所做的事情,回到任務去做一些新的事情。

這隻是預設情況,有一些activity的屬性可以控制和修改它。

alwaysRetainTaskState 屬性

如果一個任務的根activity的這個屬性設定成了"true",那麼剛才提到的那些預設行為就不會發生。這個任務保留所有的activity,甚至經過了很長一段時間。

clearTaskOnLaunch 屬性

如果任務的根activity的這個屬性設定成了”true“,那麼只要使用者離開了任務並返回,就會清除除了根activity之外的所有activity。換句話說,它和alwaysRetainTaskState正好相反,當使用者返回到任務時,總是恢複到最初的狀態,不管離開了多長時間。

finishOnTaskLaunch 屬性

這個屬性和clearTaskOnLaunch類似,但是它作用於單個activity,而不是整個任務。它可以導致任何的activity離開,包括根activity。當它設定成"true"的時候,作為任務一部分的activity只對當前會話有效。如果使用者離開然後返回到任務中。它將不再出現。

還有其他的方法強制將activity從棧中移除。如果一個行為對象包含了 FLAG_ACTIVITY_CLEAR_TOP 標誌,它的目標任務中已經有了一個這樣類型的activity執行個體,所有棧中位於這個執行個體之上的activity都會被清除,所以這個執行個體就會出現在棧頂並且對行為進行響應。如果activity被設計成"standard"模式,它也將會從棧中被清除,並且會啟動新的執行個體來處理到來的行為。這是因為當設定成”standard“模式後,對每個新的行為都會建立一個新的執行個體。

FLAG_ACTIVITY_CLEAR_TOP經常 和FLAG_ACTIVITY_NEW_TASK一起使用。當一起使用時,這些標誌是定位一個在另一個任務中存在的activity並且將它放在一個可以響應行為的地方的一種方法。

啟動任務

Activity通過將行為過濾器”android .intent.action.MAIN“設定為指定動作和"android .intent.category.LAUNCHER"作為指定類型,來成為任務的入口。(前面關於行為過濾器那一些討論的例子)。這種類型的過濾器會讓activity的表徵圖和標籤顯示在應用程式載入器上面,可以讓使用者啟動和返回activity。

第二個能力更為重要,使用者應該可以在離開一個任務一段時間後返回。因為這樣,能夠初始化任務的"singleTask"和"singleInstance"模式,只能夠用在那些擁有MAIN 和LAUNCHER 過濾器的activity中。想像一下如果沒有這兩個過濾器會發生什麼:一個行為啟動了"singleTask"模式的activity,啟動了一個新的任務並且使用者花了一些時間在這個任務上。然後使用者按下了HOME鍵,這個任務被隱藏到了後台。因為沒有在應用程式載入器上顯示它,所以就沒有辦法返回到這個任務。

一個類似的麻煩事 FLAG_ACTIVITY_NEW_TASK 標誌。如果這個標誌導致activity啟動了一個新任務,並且使用者按下HOME鍵離開了它,必須有一些方法將使用者引導回它。一些實體(像是通知管理器) 總是在一個外部的任務中啟動activity,而不作為它們的一部分,所以他們總是將帶有FLAG_ACTIVITY_NEW_TASK 標記的行為對象傳遞到startActivity() 。如果你有一個可以被外部實體使用這個標籤調用的activity,要注意使用者應該有辦法返回到啟動的任務。

對於那些你不想讓使用者返回到activity的情況,將 <activity>的finishOnTaskLaunch屬性設定為”true“,參看前面的 清理棧 一節。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.