Activity堆棧管理

 task就好像是能包含不少activity的棧。 默認狀況下,一個activity啓動另一個activity時,兩個activity是放在同一個task棧中的,第二個activity壓入第一個 activity所在的task棧。當用戶按下返回鍵時,第二個activity從棧中彈出,第一個activity又在當前屏幕顯示。這樣,從用戶角度來看,這兩個activity就好像是屬於同一個應用程序的,即便第二個activity是屬於另一個應用程序的。固然,這是指默認狀況下。 task棧包含的是activity的對象。若是一個activity有多個實例在運行,那麼棧中保存的是每一個實例的實體。棧中的activity不會從新排列,只有彈出和壓入操做。 一個task中的全部activity都以總體的形式移動。整個task能夠被移到前臺或後臺。打個比方,當前的task包含4個activity–當前 activity下面有3個activity。當用戶按下HOME鍵返回到程序啓動器(application launcher)後,選擇了一個新的應用程序(事實上是一個新的task),當前的task就被轉移到後臺,新的task中的根activity將被顯示在屏幕上。過了一段時間,用戶按返回鍵回到了程序啓動器界面,選擇了以前運行的程序(以前的task)。那個task,仍然包含着4個 activity。當用戶再次按下返回鍵時,屏幕不會顯示以前留下的那個activity(以前的task的根activity),而顯示當前 activity從task棧中移出後棧頂的那個activity。 剛剛描述的行爲是默認的activity和task的行爲。有不少方法可以改變這種行爲。activity和task之間的聯繫,以及task中的 activity的行爲能夠經過intent中的標記 以及在manifest中的<activity>元素的屬性 控制。其中,主要的Intent標記有:
android

  • 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都有一個affinity–這讓它們屬性同一個task。然而,每一個activity能夠經過<activity>中的taskAffinity屬性設置單獨的affinity。不一樣應用程序中的activity能夠共享同一個 affinity,同一個應用程序中的不一樣activity也能夠設置成不一樣的affinity。affinity屬性在2種狀況下起做用:當啓動 activity的Intent對象包含FLAG_ACTIVITY_NEW_TASK標記,或當activity的 allowTaskReparenting被設置成true。FLAG_ACTIVITY_NEW_TASK 標記app

當傳遞給startActivity()的Intent對象包含 FLAG_ACTIVITY_NEW_TASK標記時,系統會爲須要啓動的activity尋找與當前activity不一樣的task。若是要啓動的 activity的affinity屬性與當前全部的task的affinity屬性都不相同,系統會新建一個帶那個affinity屬性的task,並將要啓動的activity壓到新建的task棧中;不然將activity壓入那個affinity屬性相同的棧中。spa

allowTaskReparenting屬性code

若是一個activity的allowTaskReparenting屬性爲true,那麼它能夠從一個task(TASK1)移到另一個有相同affinity的task(TASK2)中(TASK2帶到前臺時)。對象

若是一個.apk文件從用戶角度來看包含了多個「應用程序」,你可能須要對那些 activity賦不一樣的affinity值。ci

運行模式

activity的launchMode屬性能夠有四種值:it

  • standard 」 (默認)
  • singleTop 「
  • singleTask 「
  • singleInstance 「

這4種模式能夠按4種分類來區分,如下假設位於task1中的activity1啓動activity2:io

模式/分類 包容activity2的task 一個activity是否容許有多個實例 activity是否容許有其它activity共存於一個task 對於新的intent,是否老是實例化activity對象
standard 若是不包含FLAG_ACTIVITY_NEW_TASK標記,則activity2放入 task1,不然按前面講述的規則爲activity2選擇task 可被屢次實例化,同一個task的不一樣的實例可位於不一樣的task中,每一個task也可包含多個實例 容許 是的。當接收到新的intent時,老是會生成新的activity對象。
singleTop 同standard 同standard 容許 已存在的activity對象,若是位於目標task的棧頂,則該activity被重用,若是它不位於棧頂,則會實例化新的activity對象
singleTask 將activity2放到task1棧底 不能有多個實例。因爲該模式下activity老是位於棧頂,因此actvity在同一個設備裏至多隻有一個實例 容許。singleTask模式的activity老是位於棧底位置。目標activity 實例已存在時,若是該實例恰好位於task棧頂,則接收intent,不然到來的intent將會被丟棄,但該能夠響應該intent的那個 activity所在的task將會被移到前臺。  
singleInstance 同singleTask 同singleTask 不容許與其它activity共存於一個task。若是activity1的運行在該模式下,則activity2必定與activity1位於不一樣的task  

對於新到的intent,若是是由新建立的activity對象來接收,則用戶能夠經過返回鍵回到以前的activity;若是是由已存在的 activity來接收,則用戶沒法經過返回鍵返回到接收intent以前的狀態。table

清空棧

當用戶長時間離開task(當前task被轉移到後臺)時,系統會清除task中棧底activity外的全部activity。這樣,當用戶返回到task時,只留下那個task最初始的activity了。後臺

這是默認的狀況,<activity>中有些屬性能夠改變這種行爲。

alwaysRetainTaskState屬性

若是棧底activity的這個屬性被設置爲true,剛剛描述的狀況就不會發生。 task中的全部activity將被長時間保存。

clearTaskOnLaunch屬性

若是棧底activity的這個屬性被設置爲true,一旦用戶離開task,則 task棧中的activity將被清空到只剩下棧底activity。這種狀況恰好與alwaysRetainTaskState相反。即便用戶只是短暫地離開,task也會返回到初始狀態(只剩下棧底acitivty)。

finishOnTaskLaunch屬性

這個屬性與clearTaskOnLaunch類似,但它只對單獨的activity操做,而不是整個task。它能夠結束任何activity,包括棧底的activity。當它設置爲true時,當前的activity只在當前會話期間做爲task的一部分存在,當用戶退出activity再返回時,它將不存在。

另外還有一種方法能將activity強行從stack中移出。若是intent對象包含FLAG_ACTIVITY_CLEAR_TOP 標記,當目標task中已存在與接收該intent對象的 activity類型相同的activity實例存在時,全部位於該activity對象上面的activity將被清空,這樣接收該intent的 activity就位於棧頂,能夠響應到來的intent對象。若是目標activity的運行模式爲standard,則目標activtiy也會被清空。由於當運行模式爲standard時,總會建立新的activity對象來接收到來的intent對象。

FLAG_ACTIVITY_CLEAR_TOP標記經常和FLAG_ACTIVITY_NEW_TASK一塊兒使用。用2個標記能夠定位已存在的 activity並讓它處於能夠響應intent的位置。

啓動任務(Task)

Intent filter中有」android.intent.action.MAIN 」 action和」android.intent.category.LAUNCHER 」 category的activity將被標記爲task的入口。帶有這兩個標記的activity將會顯示在應用程序啓動器(application launcher)中。

第二個比較重要的點是,用戶必須可以離開task並在以後返回。由於這個緣由,singleTask和singleInstance這兩種運行模式只能應用於含有MAIN和LAUNCHER過濾器的 activity 。打個比方,若是不包含帶MAIN和LAUNCHER過濾器,某個activity運行了一個singleTask模式的 activity,初始化了一個新的task,當用戶按下HOME鍵時,那個activity就被主屏幕「擋住」了,用戶再也沒法返回到那個 activity。

相似的狀況在FLAG_ACTIVITY_NEW_TASK標記上也會出現。若是這個標記會新建一個task,當用戶按下HOME鍵時,必須有一種方式可以讓用戶返回到那個activity。有些東西(好比notification manager)老是要求在外部task中啓動activity,在傳遞給startActivity的intent中老是包含 FLAG_ACTIVITY_NEW_TASK標記。

對於那種不但願用戶離開以後再返回activity的狀況,可將finishOnTaskLaunch屬性設置爲true。

相關文章
相關標籤/搜索