Android學習筆記14——任務和回退棧(2)

         假設當前有一個任務TaskA,在它的回退棧中有三個Activity,其他兩個在當前的Activity的下面。當用戶按下主屏幕按鈕時開啓一個新的應用程序。當新的應用程序的主界面出現的時候,TaskA就會到後臺。而新的應用程序在啓動的時候就會開啓一個自己的擁有自身Activity的棧的Task。用戶和這個新的應用程序交互以後,按下主屏幕的按鈕回到主屏幕並且選擇Task的任務圖標點擊運行。現在,TaskA回到了前臺——它所屬的回退棧中的三個Activtiy都是有效地並且棧頂的Activtiy恢復到以前的狀態。同理,在這個時候你也可以點擊主屏幕的按鈕選擇TaskB。這是一個android的多任務的例子。注意:Android允許多個任務運行在後臺。但是如果用戶一次性運行在後臺的任務太多,系統可能會因爲要回收內存而銷燬在後臺的activity,這也就造成了activity狀態的丟失。

基於以上原因,雖然android系統默認在activity停止的時候就會保存狀態,但是我們依舊應該調用activity的onSaveInstanceStatus回調方法保存activity的狀態,以避免acitvitiy被銷燬和重建。

因爲在回退棧中的Activity並不會提前計算好的,如果我們的應用程序允許在不止一個activity中打開一個特殊的activity,那麼每一次就會實例化一個新的activity實例並且壓入到棧中(而不是把之前實例化好的activity帶回到棧頂部)。如此一來,一個activity可能被實例化多次,如下圖:


這因爲如此,當用戶點擊回退按鈕時,這個activity的每一個實例都會按照被打開的順序重現。然而如果我們不想要一個activity實例多次,那麼我們可以修改這個默認行爲,以下我麼來學習如何管理Tasks。

但是在學習之前,我們首先需要總結一下Android對於Activity和Task有哪些默認行爲:

1、當Activity A開啓Activity B時,Activity A 就會停止,但是系統會保存它的狀態,當用戶在ActivtiyB點擊回退按鈕時,ActivityA就會恢復保存的狀態。

2、當用戶點擊回退按鈕離開一個Task的時候,當前的activity就會停止並且,它所在的Task也會回到後臺,系統會保存回退棧中的每一個activity的狀態。如果用戶將來選擇了開啓這個任務的圖標,使得這個任務恢復,這個就會回到前臺並且恢復這個回退棧中頂部的Activity。

3、當用戶點擊回退按鈕時,當前的activity會被從回退棧中彈出並且銷燬,而之前的activity就會被恢復。而銷燬的activity系統是不會保存它的狀態的。

那麼,這個時候我們正式開始學習如何管理Task。

正如上面所說的,android管理Task和回退棧是把所有的成功開啓的Activity放入到同一個Task和先進後出的回退棧中——這對於大多數應用程序都是起作用的,你不需要擔心你的Activity是如何關聯到Task和如何存在在回退棧中的。然而,我們可能需要去中斷默認行爲。例如我們可能需要我們的應用程序的一個activity開啓一個新的任務,而不是在當前的Task中,或者我們可能想要當開啓一個activity時帶出已經存在的實例,而不是創建一個新的實例,或者我們可能想要清空全部的activity除了根Activity,當用戶離開這個任務的時候。

我們可以在manifest文件中的activity元素中配置或者在startActivity時封裝flag到intent對象中來實現上述的這些功能。

在activity元素標籤中我們可以使用以下參數:

taskAffinity

launchMode

  • allowTaskReparenting
  • clearTaskOnLaunch
  • alwaysRetainTaskState
  • finishOnTaskLaunch
  • 在Intent的flag中可以使用:
    • FLAG_ACTIVITY_NEW_TASK
    • FLAG_ACTIVITY_CLEAR_TOP
    • FLAG_ACTIVITY_SINGLE_TOP
    • 那麼如何定義運行模式呢?
    • 運行模式允許我們定義一個activity的實例是如何和當前的Task建立相關性的。我們有兩種方式來定義運行模式的。
    • 1、在Manifest文件中配置
    • 2、使用Intent的flag屬性
    • 注意:在一些運行模式在mainfest定義是有效地但是在Intent的flag定義可能就是無效的,同理,一些運行模式在Intent的flag運行是有效地,但是在manifest文件中就可能是無效的。
    • 在manifest文件中進行運行模式的配置
    • 當我們在manifest文件中定義一個activity時,我們可以使用activity元素的launchMode這個屬性來配置這個activity是如何和一個Task相關聯的。
    • 以下是幾種我們可以爲launchMode配置的運行模式:
    • "standard":這個模式是系統默認的。它允許一個activity被實例化多次,每一個activity實例可以屬於不同的Task,也可以一個Task包含多個Activity實例。
    • "singleTop":如果一個activity的實例已經存在在當前Task的頂部,系統通過調用onNewIntent方法發送這個Intent給這個實例,而不是創建一個新的activity的實例。而其他不是頂部的activity則仍然能夠被實例化多次,每一個實例都可以屬於多個不同的Task,每一個Task可以有多個實例。例如,假設一個任務的回退棧包含A-B-C-D四個activity,D是在頂部,當一個D類的Intent到達的時候,如果運行模式是默認的standard,則系統會創建一個新的實例D,回退棧中就變爲A-B-C-D-D,但是如果運行模式是singleTop,則爲A-B-C-D;但是如果一個B類型的到達的時候,則爲A-B-C-D-B.
    • "singleTask":在一個Task的回退棧中一個activity只能存在一個實例。
    • "singleInstance":和singleTask一樣,除了是在一個Task回退棧中只有僅有一個activity.
    • 使用Intent的flag進行定義
    • 當開啓一個activity的時候,我們可以用定義startActivity方法的Intent對象的flag來修改這個activity到這個Task的相關性。
    • FLAG_ACTIVITY_NEW_TASK:在一個新的Task中開啓一個Activity,如果我們要開啓的activity的這個Task已經存在,那麼這個Task就會被置於前臺並且恢復到被存儲的狀態。這個activity會接收到這個Intent在onNewIntent()方法中。這個和上面的singleTask同樣的意思。
    • FLAG_ACTIVITY_SINGLE_TOP:如果被開啓的activity是當前的activity即是頂部的activity,那麼這個存在的實例調用onNewIntent方法,而不是創建一個activity的新的實例。這個和singleTop的運行模式相同的原理。
    • FLAG_ACTIVITY_CLEAR_TOP:如果被開啓的activity在正在運行的Task中,那麼系統不會重新創建一個實例,相反會銷燬在當前回退棧中在它之上的所有activity,通過onNewIntent方法將它置於頂部。
    • 清空回退棧
    • 如果用戶離開了一個Task太久,那麼系統會銷燬掉這個Task的除了根activity的所有activity,當用戶回到這個任務的時候,只能恢復這個根activity。系統這樣設計,是因爲考慮到當用戶離開太久的話,當回來的時候很可能放棄之前做的事情去進行一些新的操作。
    • 以下定義了一些屬性,我們可以用他們修改默認這個行爲:
    • alwaysRetainTaskState:如果一個Task的根activity的這個屬性被設置爲true,那麼這個默認的行爲不會發生,這個Task甚至在很長一段時間都保留着所有的activity。
    • clearTaskOnLaunch:如果一個Task的根activity的這個屬性被設置爲true,那麼無論用戶什麼時候離開這個Task後重新返回以後,系統會清空掉除了根activity的全部activity。換而言之,它是alwaysRetainTaskState的相反的意思。用戶哪怕離開這個Task一會兒,用戶總是返回到初始的狀態。
    • finishOnTaskLaunch:這個屬性和clearTaskOnLaunch很相似,但是它僅僅操作一個單獨的activity,而不是整個Task。它也清空包括acitiviy的所有的activity。如果這個屬性被設置爲true,這個activity僅僅保持當前session的Task的部分actvitiy。如果用戶離開後返回這些activity將不會呈現。

發佈了43 篇原創文章 · 獲贊 25 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章