Android任務和返回棧完全解析,細數那些你所不知道的細節,android細數

來源:互聯網
上載者:User

Android任務和返回棧完全解析,細數那些你所不知道的細節,android細數

轉載請註明出處:http://blog.csdn.net/guolin_blog/article/details/41087993

本篇文章主要內容來自於Android Doc,我翻譯之後又做了些加工,英文好的朋友也可以直接去讀原文。

http://developer.android.com/guide/components/tasks-and-back-stack.html

任務和返回棧

一個應用程式當中通常都會包含很多個Activity,每個Activity都應該設計成為一個具有特定的功能,並且可以讓使用者進行操作的組件。另外,Activity之間還應該是可以相互啟動的。比如,一個郵件應用中可能會包含一個用於展示郵件清單的Activity,而當使用者點擊了其中某一封郵件的時候,就會開啟另外一個Activity來顯示該封郵件的具體內容。

除此之外,一個Activity甚至還可以去啟動其它應用程式當中的Activity。打個比方,如果你的應用希望去發送一封郵件,你就可以定義一個具有"send"動作的Intent,並且傳入一些資料,如對方郵箱地址、郵件內容等。這樣,如果另外一個應用程式中的某個Activity聲明自己是可以響應這種Intent的,那麼這個Activity就會被開啟。在當前情境下,這個Intent是為了要發送郵件的,所以說郵件應用程式當中的編寫郵件Activity就應該被開啟。當郵件發送出去之後,仍然還是會回到你的應用程式當中,這讓使用者看起來好像剛才那個編寫郵件的Activity就是你的應用程式當中的一部分。所以說,即使有很多個Activity分別都是來自於不同應用程式的,Android系統仍然可以將它們無縫地結合到一起,之所以能實現這一點,就是因為這些Activity都是存在於一個相同的任務(Task)當中的。

任務是一個Activity的集合,它使用棧的方式來管理其中的Activity,這個棧又被稱為返回棧(back stack),棧中Activity的順序就是按照它們被開啟的順序依次存放的。

手機的Home介面是大多數任務開始的地方,當使用者在Home介面上點擊了一個應用的表徵圖時,這個應用的任務就會被轉移到前台。如果這個應用目前並沒有任何一個任務的話(說明這個應用最近沒有被啟動過),系統就會去建立一個新的任務,並且將該應用的主Activity放入到返回棧當中。

當一個Activity啟動了另外一個Activity的時候,新的Activity就會被放置到返回棧的棧頂並將獲得焦點。前一個Activity仍然保留在返回棧當中,但會處於停止狀態。當使用者按下Back鍵的時候,棧中最頂端的Activity會被移除掉,然後前一個Activity則會得重新回到最頂端的位置。返回棧中的Activity的順序永遠都不會發生改變,我們只能向棧頂添加Activity,或者將棧頂的Activity移除掉。因此,返回棧是一個典型的後進先出(last in, first out)的資料結構。通過時間軸的方式非常清晰地向我們展示了多個Activity在返回棧當中的狀態變化:


如果使用者一直地按Back鍵,這樣返回棧中的Activity會一個個地被移除,直到最終返回到主畫面。當返回棧中所有的Activity都被移除掉的時候,對應的任務也就不存在了。

任務除了可以被轉移到前台之外,當然也是可以被轉移到背景。當使用者開啟了一個新的任務,或者點擊Home鍵回到主畫面的時候,之前任務就會被轉移到後台了。當任務處於後台狀態的時候,返回棧中所有的Activity都會進入停止狀態,但這些Activity在棧中的順序都會原封不動地保留著,如所示:


這個時候,使用者還可以將任意背景任務切換到前台,這樣使用者應該就會看到之前離開這個任務時處於最頂端的那個Activity。舉個例子來說,當前任務A的棧中有三個Activity,現在使用者按下Home鍵,然後點擊案頭上的表徵圖啟動了另外一個應用程式。當系統回到案頭的時候,其實任務A就已經進入後台了,然後當另外一個應用程式啟動的時候,系統會為這個程式開啟一個新的任務(任務B)。當使用者使用完這個程式之後,再次按下Home鍵回到案頭,這個時候任務B也進入了後台。然後使用者又重新開啟了第一次使用的程式,這個時候任務A又會回到前台,A任務棧中的三個Activity仍然會保留著剛才的順序,最頂端的Activity將重新變為運行狀態。之後使用者仍然可以通過Home鍵或者多任務鍵來切換回任務B,或者啟動更多的任務,這就是Android中多任務切換的例子。

由於返回棧中的Activity的順序永遠都不會發生改變,所以如果你的應用程式中允許有多個入口都可以啟動同一個Activity,那麼每次啟動的時候就都會建立該Activity的一個新的執行個體,而不是將下面的Activity的移動到棧頂。這樣的話就容易導致一個問題的產生,即同一個Activity有可能會被執行個體化很多次,如所示:


但是呢,如果你不希望同一個Activity可以被多次執行個體化,那當然也是可以的,馬上我們就將開始討論如果實現這一功能,現在我們先把預設的任務和Activity的行為簡單概括一下:

  • 當Activity A啟動Activity B時,Activity A進入停止狀態,但系統仍然會將它的所有相關資訊保留,比如滾動的位置,還有文字框輸入的內容等。如果使用者在Activity B中按下Back鍵,那麼Activity A將會重新回到運行狀態。
  • 當使用者通過Home鍵離開一個任務時,該任務會進入後台,並且返回棧中所有的Activity都會進入停止狀態。系統會將這些Activity的狀態進行保留,這樣當使用者下一次重新開啟這個應用程式時,就可以將背景工作直接提取到前台,並將之前最頂端的Activity進行恢複。
  • 當使用者按下Back鍵時,當前最頂端的Activity會被從返回棧中移除掉,移除掉的Activity將被銷毀,然後前面一個Activity將處於棧頂位置並進入活動狀態。當一個Activity被銷毀了之後,系統不會再為它保留任何的狀態資訊。
  • 每個Activity都可以被執行個體化很多次,即使是在不同的任務當中。
管理工作

Android系統管理任務和返回棧的方式,正如上面所描述的一樣,就是把所有啟動的Activity都放入到一個相同的任務當中,通過一個“後進先出”的棧來進行管理的。這種方式在絕大多數情況下都是沒問題的,開發人員也無須去關心任務中的Activity到底是怎麼樣存放在返回棧當中的。但是呢,如果你想打破這種預設的行為,比如說當啟動一個新的Activity時,你希望它可以存在於一個獨立的任務當中,而不是現有的任務當中。或者說,當啟動一個Activity時,如果這個Activity已經存在於返回棧中了,你希望能把這個Activity直接移動到棧頂,而不是再建立一個它的執行個體。再或者,你希望可以將返回棧中除了最底層的那個Activity之外的其它所有Activity全部清除掉。這些功能甚至更多功能,都是可以通過在manifest檔案中設定<activity>元素的屬性,或者是在啟動Activity時配置Intent的flag來實現的。

在<activity>元素中,有以下幾個屬性是可以使用的:

  • taskAffinity
  • launchMode
  • allowTaskReparenting
  • clearTaskOnLaunch
  • alwaysRetainTaskState
  • finishOnTaskLaunch

而在Intent當中,有以下幾個flag是比較常用的:

  • FLAG_ACTIVITY_NEW_TASK
  • FLAG_ACTIVITY_CLEAR_TOP
  • FLAG_ACTIVITY_SINGLE_TOP

下面我們就將開始討論,如何通過manifest參數,以及Intent flag來改變Activity在任務中的預設行為。

定義啟動模式

啟動模式允許你去定義如何將一個Activity的執行個體和當前的任務進行關聯,你可以通過以下兩種不同的方式來定義啟動模式:

1.使用manifest檔案

當你在manifest檔案中聲明一個Activity的時候,你可以指定這個Activity在啟動的時候該如何與任務進行關聯。

2.使用Intent flag

當你調用startActivity()方法時,你可以在Intent中加入一個flag,從而指定新啟動的Activity該如何與當前任務進行關聯。

也就是說,如果Activity A啟動了Activity B,Activity B可以定義自己該如何與當前任務進行關聯,而Activity A也可以要求Activity B該如何與當前任務進行關聯。如果Activity B在manifest中已經定義了該如何與任務進行關聯,而Activity A同時也在Intent中要求了Activity B該怎麼樣與當前任務進行關聯,那麼此時Intent中的定義將覆蓋manifest中的定義。

需要注意的是,有些啟動模式在manifest中可以指定,但在Intent中是指定不了的。同樣,也有些啟動模式在Intent中可以指定,但在manifest中是指定不了的,下面我們就來具體討論一下。

使用manifest檔案

當在manifest檔案中定義Activity的時候,你可以通過<activity>元素的launchMode屬性來指定這個Activity應該如何與任務進行關聯。launchMode屬性一共有以下四種選擇性參數:

"standard"(預設啟動模式)

standard是預設的啟動模式,即如果不指定launchMode屬性,則自動就會使用這種啟動模式。這種啟動模式表示每次啟動該Activity時系統都會為建立一個新的執行個體,並且總會把它放入到當前的任務當中。聲明成這種啟動模式的Activity可以被執行個體化多次,一個任務當中也可以包含多個這種Activity的執行個體。

"singleTop"

這種啟動模式表示,如果要啟動的這個Activity在當前任務中已經存在了,並且還處於棧頂的位置,那麼系統就不會再去建立一個該Activity的執行個體,而是調用棧頂Activity的onNewIntent()方法。聲明成這種啟動模式的Activity也可以被執行個體化多次,一個任務當中也可以包含多個這種Activity的執行個體。

舉個例子來講,一個任務的返回棧中有A、B、C、D四個Activity,其中A在最底端,D在最頂端。這個時候如果我們要求再啟動一次D,並且D的啟動模式是"standard",那麼系統就會再建立一個D的執行個體放入到返回棧中,此時棧內元素為:A-B-C-D-D。而如果D的啟動模式是"singleTop"的話,由於D已經是在棧頂了,那麼系統就不會再建立一個D的執行個體,而是直接調用D Activity的onNewIntent()方法,此時棧內元素仍然為:A-B-C-D。

"singleTask"

這種啟動模式表示,系統會建立一個新的任務,並將啟動的Activity放入這個新任務的棧底位置。但是,如果現有任務當中已經存在一個該Activity的執行個體了,那麼系統就不會再建立一次它的執行個體,而是會直接調用它的onNewIntent()方法。聲明成這種啟動模式的Activity,在同一個任務當中只會存在一個執行個體。注意這裡我們所說的啟動Activity,都指的是啟動其它應用程式中的Activity,因為"singleTask"模式在預設情況下只有啟動其它程式的Activity才會建立一個新的任務,啟動自己程式中的Activity還是會使用相同的任務,具體原因會在下面 處理affinity 部分進行解釋。

"singleInstance"

這種啟動模式和"singleTask"有點相似,只不過系統不會向聲明成"singleInstance"的Activity所在的任務當中再添加其它Activity。也就是說,這種Activity所在的任務中始終只會有一個Activity,通過這個Activity再開啟的其它Activity也會被放入到別的任務當中。

再舉一個例子,Android系統內建的瀏覽器程式聲明自己瀏覽網頁的Activity始終應該在一個獨立的任務當中開啟,也就是通過在<activity>元素中設定"singleTask"啟動模式來實現的。這意味著,當你的程式準備去開啟Android內建瀏覽器的時候,新開啟的Activity並不會放入到你當前的任務中,而是會啟動一個新的任務。而如果瀏覽器程式在後台已經存在一個任務了,則會把這個任務切換到前台。

其實不管是Activity在一個新任務當中啟動,還是在當前任務中啟動,返回鍵永遠都會把我們帶回到之前的一個Activity中的。但是有一種情況是比較特殊的,就是如果Activity指定了啟動模式是"singleTask",並且啟動的是另外一個應用程式中的Activity,這個時候當發現該Activity正好處於一個背景工作當中的話,就會直接將這整個背景工作一起切換到前台。此時按下返回鍵會優先將目前最前台的任務(剛剛從後台切換到最前台)進行回退,比較形象地展示了這種情況:


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.