Android學習之 Activity堆疊管理與控制

小呂-ICE發表於2014-11-08

    App程式中有很多Activity、你可以通俗的理解為把一個Activity看做是一個UI介面。在Andord系統中Activity是以堆疊<堆疊的特性:只有壓入和彈出  先進後出>的形式存在。堆疊中的根Activity就是應用程式的啟動Activity。而堆疊中最上方的Activity則是當前執行的/使用者正在操作的UI Activity。

    也可以這樣去理解:堆疊中儲存的是Activity物件,如果一個應用中多次使用了一個Activity,那麼就會使同一個任務中出現多個該Activity的物件。一個程式在執行、他所啟動的Activity通常情況下<注意是通常情況下>在同一個堆疊中、這個也叫做任務棧<Task>。

    Activity和Task的關聯: Activity在任務中的行為,受控於啟動Activity的行為物件的標誌位和清單檔案中的<activity> 元素的屬性的互相作用。

    

主要的行為標誌有:

FLAG_ACTIVITY_NEW_TASK 

FLAG_ACTIVITY_CLEAR_TOP 

FLAG_ACTIVITY_SINGLE_TOP

..............等


主要的<activity>屬性有:

launchMode 

taskAffinity 

allowTaskReparenting 

alwaysRetainTaskState

clearTaskOnLaunch 

finishOnTaskLaunch


下面將對每一個屬性和標誌一一介紹:

[雖然全是文字說明,稍有枯味、但只要你細細消化 相信使你對Activity棧的管理會進一步理解]

<activity>屬性:

1、launchMode:Activity 4種啟動模式  

     1>、standard: <預設啟動模式>

           在任務棧中總是建立一個新的Activity例項

     2>、singleTop:

           在任務棧中如果有存在一個和新啟動Activity相同的Activity正在棧頂則不再建立一個新的Activity,即不再調         用onCreate(),而是通過呼叫onNewIntent()方法。如果不存在棧頂,這時候就和standard一樣建立一個新的             Activity例項,走onCreate()方法。

      3>、singleTask:

             ①設定了"singleTask"啟動模式的Activity,它在啟動的時候,會先在系統中查詢屬性值affinity等於它的屬性        值taskAffinity的Task存在;如果存在這樣的Task,它就會在這個Task中啟動,否則就會在新的任務棧中啟動。        因此,如果我們想要設定了"singleTask"啟動模式的Activity在新的任務中啟動,就要為它設定一個獨立的taskAffinity屬性值。

            ② 如果設定了"singleTask"啟動模式的Activity不是在新的任務中啟動時,它會在已有的任務中檢視是否已經        存在相應的Activity例項,如果存在,就會把位於這個Activity例項上面的Activity全部結束掉,即最終這個Activity 例項會位於任務的Stack頂端中。

            ③ 在一個任務棧中只有一個”singleTask”啟動模式的Activity存在。他的上面可以有其他的Activity。這點與singleInstance是有區別的。

       4>、singleInstance:

             在一個新的任務棧中啟動,且該棧中有且只有他一個Activity例項、不允許有其他的Activity成員存在。

             永遠他一個。


2、android:taskAffinity: task親和力

      通常來說一個程式內/任務棧中的Activity具有親和力,也就是說具有相同親和力的Activity預設屬於同一個任務Task中,

     affinity決定兩件事情——Activity重新宿主(從一個Task跳到了另一個Task中,新的Task就被稱為重新宿主)的Task(參考allowTaskReparenting特性)和使用FLAG_ACTIVITY_NEW_TASK標誌啟動的Activity宿主的Task。

     預設情況,一個應用程式中的所有Activity都擁有相同的affinity。你可以通過設定這個特性來重組它們,甚至可以把不同應用程式中定義的Activity放置到相同的Task中。如果不指定改activity到底屬於哪個task,則可以將affinity設定為空字串。如果這個特性沒有設定,Activity將從應用程式的設定那裡繼承下來(參考<application>元素的taskAffinity特性)。應用程式預設的affinity的名字是<manifest>元素中設定的package名。

      注意:affinity只有在載入activity的Intent物件包含了FLAG_ACTIVITY_NEW_TASK 標記,或者當activity的allowTaskReparenting屬性設定為“true”時才有效。


3、android:allowTaskReparenting:是否允許Activity跳轉/更改Task

     用來標記Activity能否從啟動的Task移動到有著相同affinity的Task(當這個Task進入到前臺時)——“true”,表示能移動,“false”,表示它必須呆在啟動時的那個Task裡。如果這個特性沒有被設定,設定到<application>元素上的allowTaskReparenting特性的值會應用到Activity上。預設值為“false”。

      一般來說,當Activity啟動後,它就與啟動它的Task關聯,並且在那裡耗盡它的整個生命週期。噹噹前的Task不再顯示時,你可以使用這個特性來強制Activity移動到有著affinity的Task中。典型用法是:把一個應用程式的Activity移到另一個應用程式的主Task中。


4、android:alwaysRetainTaskState:當按下Home主鍵將程式退回至後臺執行,再回到前臺時是否保留Task狀態

     用來標記Activity所在的Task的狀態是否總是由系統來保持——“true”,表示總是;“false”,表示在某種情形下允許系統恢復Task到它的初始化狀態。預設值是“false”。這個特性只針對Task的根Activity有意義;對其它Activity來說,忽略之。

     一般來說,特定的情形如當使用者從主畫面重新選擇這個Task時,系統會對這個Task進行清理(從stack中刪除位於根Activity之上的所有Activivity)。典型的情況,當使用者有一段時間沒有訪問這個Task時也會這麼做,例如30分鐘。

然而,當這個特性設為“true”時,使用者總是能回到這個Task的最新狀態,無論他們是如何啟動的。這非常有用,例如,像Browser應用程式,這裡有很多的狀態(例如多個開啟的Tab),使用者不想丟失這些狀態。系統會為我們保持這些狀態資料。


5、android:clearTaskOnLaunch:當按下Home主鍵將程式退回至後臺執行,再回到前臺時是否清除/移除除了跟Activity<啟動Activity>之外的所有Activity。

     用來標記是否從Task中清除所有的Activity,除了根Activity外(每當從主畫面重新啟動時)——“true”,表示總是清除至它的根Activity,“false”表示不。預設值是“false”。這個特性只對啟動一個新的Task的Activity(根Activity)有意義;對Task中其它的Activity忽略。

    當這個值為“true”,每次使用者重新啟動這個Task時,都會進入到它的根Activity中,不管這個Task最後在做些什麼,也不管使用者是使用BACK還是HOME離開的。當這個值為“false”時,可能會在一些情形下(參考alwaysRetainTaskState特性)清除Task的Activity,但不總是。

    假設,某人從主畫面啟動了ActivityP,並從那裡遷移至Activity Q。接下來使用者按下HOME,然後返回Activity P。一般,使用者可能見到的是Activity Q,因為它是P的Task中最後工作的內容。然而,如果P設定這個特性為“true”,當使用者按下HOME並使這個Task再次進入前臺時,其上的所有的Activity(在這裡是Q)都將被清除。因此,當返回到這個Task時,使用者只能看到P。如果這個特性和allowTaskReparenting都設定為“true”,那些能重新宿主的Activity會移動到共享affinity的Task中;剩下的Activity都將被拋棄。


6、android:finishOnTaskLaunch:當按下Home主鍵將程式退回至後臺執行,再回到前臺時是否關閉/結束掉退回到後臺之前的Activity.

     用來標記當使用者再次啟動它的Task(在主畫面選擇這個Task)時已經存在的Activity例項是否要關閉(結束)——“true”,表示應該關閉,“false”表示不關閉。預設值是“false”
如果這個特性和allowTaskReparenting都設定為“true”,這個特性勝出,Activityaffinity忽略。這個Activity不會重新宿主,但是會銷燬。



通過Intent設定的屬性標識:

形式如下:

Intent intent = new Intent(SwitchActivity.this, ThredActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);


1、FLAG_ACTIVITY_NEW_TASK

     在預設情況下,一個新Activity被另一個Activity呼叫了startActivity()方法,載入任務之中。並壓入了呼叫者所在的堆疊。然而,如果傳遞給startActivity()Intent物件包含了FLAG_ACTIVITY_NEW_TASK標記,系統會為新Activity安排另外一個任務。一般情況下,如同標記所暗示的那樣,這會是一個新任務。然而,這並不是必然的。如果已經存在了一個與新Activity有著同樣affinity的任務,則Activity會載入那個任務之中。如果沒有,則啟用新任務。

簡言之:有相同affinity的任務,則壓入該任務,否則建立一個新的任務。


2、FLAG_ACTIVITY_CLEAR_TOP

      如果intent將要啟動的Activity已經存在於一個Task中,那麼這個Task中該Activity上面的那些Activity都會被移除銷燬,然後這個intent將會作為一個新的intent投遞給目標Activity(目標Activity已經位於棧的頂端了)。

     這個啟動模式還可以與FLAG_ACTIVITY_NEW_TASK結合起來使用:用於啟動一個Task中的根Activity,它會把那個Task中任何執行的例項帶入前臺,然後清除它直到根Activity。這非常有用,例如,當從NotificationManager處啟動一個Activity


3、FLAG_ACTIVITY_SINGLE_TOP

     如果設定,當這個Activity位於歷史stack的頂端執行時,不再啟動一個新的。
     同 android: launchMode = “singleTop”


4、FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

     如果設定,新的Activity不會在最近啟動的Activity的列表中儲存。


以上只介紹了常有用的幾種控制Activity跳轉的Flag標識

更多詳細前往 http://android.toolib.net/reference/android/content/Intent.html 進行學習。






相關文章