android面試02-Activity啓動模式 及 Intent Flags 與 棧 的關聯分析

在學習Android的過程中,Intent是我們最常用Android用於進程內或進程間通信的機制,其底層的通信是以Binder機制實現的,在物理層則是通過共享內存的方式實現的。

Intent主要用於2種情景下:(1)發起意圖  (2)廣播

它的屬性有:ComponentName,action,data,category,extras,flags等,通常情況下,進行Intent的匹配涉及到3個屬性:Action,Data,Category。這些東西都需要了解才能對它有個深入的體會。

1.什麼是棧

2.Activity棧

3.Task

4.Activity啓動模式

5.Activity棧和Task聯繫

6.Intent Flags

7.Activity相關屬性taskAffinity

1.什麼是棧


棧是一種常用的數據結構,棧只允許訪問棧頂的元素,棧就像一個杯子,每次都只能取杯子頂上的東西,而對於棧就只能每次訪問它的棧頂元素,從而可以達到保護棧頂元素以下的其他元素.”先進後出”或”後進先出”就是棧的一大特點,先進棧的元素總是要等到後進棧的元素出棧以後才能出棧.遞歸就是利用到了系統棧,暫時保存臨時結果,對臨時結果進行保護.
定義棧(Stack)棧的定義棧(Stack)是限制僅在表的一端進行插入和刪除運算的線性表。(1)通常稱插入、刪除的這一端爲棧頂(Top),另一端稱爲棧底(Bottom)。 (2)當表中沒有元素時稱爲空棧。(3)棧爲後進先出(Last In First Out)的線性表,簡稱爲LIFO表。棧的修改是按後進先出的原則進行。每次刪除(退棧)的總是當前棧中”最新”的元素,即最後插入(進棧)的元素,而最先插入的是被放在棧的底部,要到最後才能刪除。
棧的操作:壓棧、彈棧
2.Activity中的棧
Android的管理主要是通過Activity棧來進行,當一個Activity啓動時,系統會根據其配置將它壓入到一個特定的棧中,系統處於運行狀態。當用戶點擊返回或則FINISH()了該Activity,那麼它便會被從棧中壓出,隨之摧毀,按照Activity的生命週期可以知道,如果當前顯示的棧中Activity沒有被摧毀,那麼打開新的Activity時候,會將新打開的壓入到棧,原來的根據其顯示情況選擇狀態變化(原Activity依舊可見,變爲暫停狀態(Paused),如果被完成遮住了,轉變爲停止狀態(Stopped))。
3.Task

Task是與Activity相關的一個重要概念,它密切聯繫着Activity棧,它簡單的說,就是一組以棧的模式聚集在一起的Activity組件集合。(這裏只提它和Activity的啓動模式來講)

4.Activity啓動模式

屬性:android:launchMode

作用:用於指示Activity如何啓動。

描述:這裏有四種模式,與Intent對象中的Activity Flags的屬性(FLAG_ACTIVITY_*變量)共同作用,來決定Activity如何啓動來處理Intent。

四種模式:

“standard”  –默認模式
“singleTop”
“singleTask”
“singleInstance”

以下舉例說明它們的區別:

standard:Activity的默認加載方法,該方法會通過跳轉到一個新的activity,同時將該實例壓入到棧中(不管該activity是否已經存在在Task棧中,都是採用new操作)。例如: 棧中順序是A B C D ,此時D通過Intent跳轉到A,那麼棧中結構就變成 A B C D A ,點擊返回按鈕的 顯示順序是 D C B A,依次摧毀。

singleTop:singleTop模式下,當前Activity D位於棧頂的時候,如果通過Intent跳轉到它本身的Activity (即D),那麼不會重新創建一個新的D實例,所以棧中的結構依舊爲A B C D,如果跳轉到B,那麼由於B不處於棧頂,所以會新建一個B實例並壓入到棧中,結構就變成了A B C D B。

singleTask:singleTask模式下,Task棧中只能有一個對應Activity的實例。例如:現在棧的結構爲:A B C D。此時D通過Intent跳轉到B,則棧的結構變成了:A B。其中的C和D被棧彈出銷燬了,也就是說位於B之上的實例都被銷燬了。

singleInstance:singleInstance模式下,會將打開的Activity壓入一個新建的任務棧中。例如:Task棧1中結構爲:A B C ,C通過Intent跳轉到了D(D的模式爲singleInstance),那麼則會新建一個Task 棧2,棧1中結構依舊爲A B C,棧2中結構爲D,此時屏幕中顯示D,之後D通過Intent跳轉到D,棧2中不會壓入新的D,所以2個棧中的情況沒發生改變。如果D跳轉到了C,那麼就會根據C對應的launchMode的在棧1中進行對應的操作,C如果爲standard,那麼D跳轉到C,棧1的結構爲A B C C ,此時點擊返回按鈕,還是在C,棧1的結構變爲A B C,而不會回到D。

5.Activity棧和Task聯繫

Task簡單的就是一組以棧的模式聚集在一起的Activity組件集合,類似於一個填充了Activity的容器,最先加入的Activity會處於容器最下面,最後加入的處於容器最上面,而從Task中取出Activity是從最頂端先取出,最後取出的是最開始添加Activity,這就是後進先出(Last
In First Out)模式,而Activity在Task中的順序是可以控制的,在Activity跳轉時用到Intent Flag可以設置新建activity的創建方式(這裏就涉及到了Intent
Flag的使用)。

6.Intent Flags

Flags: 表示Intent的標誌位,常用於Activity的場景中,它和Activity的啓動模式有着密切的聯繫。

下面列舉的是和本文主題相關的Flags屬性:

Intent.FLAG_ACTIVITY_NEW_TASK (默認)

默認的跳轉類型,它會重新創建一個新的Activity,不過與這種情況,比如說Task1中有A,B,C三個Activity,此時在C中啓動D的話,如果在AndroidManifest.xml文件中給D添加了Affinity的值和Task中的不一樣的話,則會在新標記的Affinity所存在的Task中壓入這個Activity。如果是默認的或者指定的Affinity和Task一樣的話,就和標準模式一樣了啓動一個新的Activity.

FLAG_ACTIVITY_SINGLE_TOP

這個FLAG就相當於啓動模式中的singletop,例如:原來棧中結構是A B C D,在D中啓動D,棧中的情況還是A,B,C,D。

FLAG_ACTIVITY_CLEAR_TOP

這個FLAG就相當於啓動模式中的SingleTask,這種FLAG啓動的Activity會把要啓動的Activity之上的Activity全部彈出棧空間。例如:原來棧中的結構是A B C D ,從D中跳轉到B,棧中的結構就變爲了A B了。(這個方法可以用來關閉多個Activity,之後的一篇博文裏面會提到)

FLAG_ACTIVITY_BROUGHT_TO_FRONT

這個網上很多人是這樣寫的。如果activity在task存在,拿到最頂端,不會啓動新的Activity。這個有可能會誤導大家! 他這個FLAG其實是這個意思!比如說我現在有A,在A中啓動B,此時在A中Intent中加上這個標記。此時B就是以FLAG_ACTIVITY_BROUGHT_TO_FRONT方式啓動,此時在B中再啓動C,D(正常啓動C,D),如果這個時候在D中再啓動B,這個時候最後的棧的情況是 A,C,D,B。如果在A,B,C,D正常啓動的話,不管B有沒有用FLAG_ACTIVITY_BROUGHT_TO_FRONT啓動,此時在D中啓動B的話,還是會變成A,C,D,B的。

FLAG_ACTIVITY_NO_USER_ACTION

onUserLeaveHint()作爲activity週期的一部分,它在activity因爲用戶要跳轉到別的activity而要退到background時使用。比如,在用戶按下Home鍵,它將被調用。比如有電話進來(不屬於用戶的選擇),它就不會被調用。

那麼系統如何區分讓當前activity退到background時使用是用戶的選擇?

它是根據促使當前activity退到background的那個新啓動的Activity的Intent裏是否有FLAG_ACTIVITY_NO_USER_ACTION來確定的。

注意:調用finish()使該activity銷燬時不會調用該函數

FLAG_ACTIVITY_NO_HISTORY

意思就是說用這個FLAG啓動的Activity,一旦退出,它不會存在於棧中,比方說!原來是A,B,C這個時候再C中以這個FLAG啓動D的,D再啓動E,這個時候棧中情況爲A,B,C,E。

7.Activity相關屬性taskAffinity

Activity 中的 android:taskAffinity 這個屬性介紹:

Activity爲Task擁有的一個affinity。擁有相同的affinity的Activity理論上屬於相同的Task(在用戶的角度是相同的“應用程序”)。Task的affinity是由它的根Activity決定的。
affinity決定兩件事情——Activity重新宿主的Task(參考allowTaskReparenting特性)和使用FLAG_ACTIVITY_NEW_TASK標誌啓動的Activity宿主的Task。
默認情況,一個應用程序中的所有Activity都擁有相同的affinity。捏可以設定這個特性來重組它們,甚至可以把不同應用程序中定義的Activity放置到相同的Task中。爲了明確Activity不宿主特定的Task,設定該特性爲空的字符串。
如果這個特性沒有設置,Activity將從應用程序的設定那裏繼承下來(參考<application>元素的taskAffinity特性)。應用程序默認的affinity的名字是<manifest>元素中設定的package名。

注:以上的android:taskAffinity只有通過標誌位爲FLAG_ACTIVITY_NEW_TASK的Intent啓動Activity時,該Activity的這個屬性纔會生效,系統纔會將具有相同Task親和力的Task切換到前臺,然後啓動該Activity,否則該Activity仍然運行在啓動它的Task中。

上面總結了下Activity啓動模式 及 Intent Flags 與 棧 的關聯分析,便於之後一篇文章中跳轉模式的瞭解使用。

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