先首先簡單介紹下Task和Activity的關系
?
Task就像一個容器,而Activity就相當與填充這個容器的東西,第一個東西(Activity)則會處于最下面,最后添加的東西(Activity)則會在最上面。從Task中取出東西(Activity)是從最頂端取出,也就是說最先取出的是最后添加的東西(Activity),以此類推,最后取出的是第一次添加的Activity,而Activity在Task中的順序是可以控制的,在Activity跳轉時用到Intent Flag可以設置新建activity的創建方式;
??
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了
?
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。
?
**********************************************************************
?
Activity有四種加載模式:standard(默認), singleTop, singleTask和 singleInstance。以下逐一舉例說明他們的區別:
standard:Activity的默認加載方法,即使某個Activity在 Task棧中已經存在,另一個activity通過Intent跳轉到該activity,同樣會新創建一個實例壓入棧中。例如:現在棧的情況為:A B C D,在D這個Activity中通過Intent跳轉到D,那么現在的棧情況為: A B C D D 。此時如果棧頂的D通過Intent跳轉到B,則棧情況為:A B C D D B。此時如果依次按返回鍵,D??D C B A將會依次彈出棧而顯示在界面上。
singleTop:如果某個Activity的Launch mode設置成singleTop,那么當該Activity位于棧頂的時候,再通過Intent跳轉到本身這個Activity,則將不會創建一個新的實例壓入棧中。例如:現在棧的情況為:A B C D。D的Launch mode設置成了singleTop,那么在D中啟動Intent跳轉到D,那么將不會新創建一個D的實例壓入棧中,此時棧的情況依然為:A B C D。但是如果此時B的模式也是singleTop,D跳轉到B,那么則會新建一個B的實例壓入棧中,因為此時B不是位于棧頂,此時棧的情況就變成了:A B C D B。
singleTask:如果某個Activity是singleTask模式,那么Task棧中將會只有一個該Activity的實例。例如:現在棧的情況為:A B C D。B的Launch mode為singleTask,此時D通過Intent跳轉到B,則棧的情況變成了:A B。而C和D被彈出銷毀了,也就是說位于B之上的實例都被銷毀了。
singleInstance:將Activity壓入一個新建的任務棧中。例如:Task棧1的情況為:A B C。C通過Intent跳轉到D,而D的Launch mode為singleInstance,則將會新建一個Task棧2。此時Task棧1的情況還是為:A B C。Task棧2的情況為:D。此時屏幕界面顯示D的內容,如果這時D又通過Intent跳轉到D,則Task棧2中也不會新建一個D的實例,所以兩個棧的情況也不會變化。而如果D跳轉到C,則棧1的情況變成了:A B C C,因為C的Launch mode為standard,此時如果再按返回鍵,則棧1變成:A B C。也就是說現在界面還顯示C的內容,不是D。
好了,現在有一個問題就是這時這種情況下如果用戶點擊了Home鍵,則再也回不到D的即時界面了。如果想解決這個問題,可以為D在Manifest.xml文件中的聲明加上
?????????????????????????????????????????????????
?????????????????????????????????????????????????
??????????????????????????????????????????????
加上這段之后,也就是說該程序中有兩個這種聲明,另一個就是那個正常的根 activity,在打成apk包安裝之后,在程序列表中能看到兩個圖標,但是如果都運行的話,在任務管理器中其實也只有一個。上面的情況點擊D的那個圖標就能回到它的即時界面(比如一個EditText,以前輸入的內容,現在回到之后依然存在)。
/
Intent的常用Flag參數:
FLAG_ACTIVITY_CLEAR_TOP:例如現在的棧情況為:A B C D 。D此時通過intent跳轉到B,如果這個intent添加FLAG_ACTIVITY_CLEAR_TOP 標記,則棧情況變為:A B。如果沒有添加這個標記,則棧情況將會變成:A B C D B。也就是說,如果添加了FLAG_ACTIVITY_CLEAR_TOP 標記,并且目標Activity在棧中已經存在,則將會把位于該目標activity之上的activity從棧中彈出銷毀。這跟上面把B的Launch mode設置成singleTask類似。
FLAG_ACTIVITY_NEW_TASK:例如現在棧1的情況是:A B C。C通過intent跳轉到D,并且這個intent添加了FLAG_ACTIVITY_NEW_TASK 標記,如果D這個Activity在Manifest.xml中的聲明中添加了Task affinity,并且和棧1的affinity不同,系統首先會查找有沒有和D的Task affinity相同的task棧存在,如果有存在,將D壓入那個棧,如果不存在則會新建一個D的affinity的棧將其壓入。如果D的Task affinity默認沒有設置,或者和棧1的affinity相同,則會把其壓入棧1,變成:A B C D,這樣就和不加FLAG_ACTIVITY_NEW_TASK 標記效果是一樣的了。??????注意如果試圖從非activity的非正常途徑啟動一個activity,比如從一個service中啟動一個activity,則intent比如要添加FLAG_ACTIVITY_NEW_TASK 標記。
FLAG_ACTIVITY_NO_HISTORY:例如現在棧情況為:A B C。C通過intent跳轉到D,這個intent添加FLAG_ACTIVITY_NO_HISTORY標志,則此時界面顯示D的內容,但是它并不會壓入棧中。如果按返回鍵,返回到C,棧的情況還是:A B C。如果此時D中又跳轉到E,棧的情況變為:A B C E,此時按返回鍵會回到C,因為D根本就沒有被壓入棧中。
?FLAG_ACTIVITY_SINGLE_TOP:和上面Activity的 Launch mode的singleTop類似。如果某個intent添加了這個標志,并且這個intent的目標activity就是棧頂的activity,那么將不會新建一個實例壓入棧中。
?/
Activity的主要屬性:
allowTaskReparenting:設置成true時,和Intent的FLAG_ACTIVITY_NEW_TASK 標記類似。
alwaysRetainTaskStat:???如果用戶長時間將某個task 移入后臺,則系統會將該task的棧內容彈出只剩下棧底的activity,此時用戶再返回,則只能看到根activity了。如果棧底的 activity的這個屬性設置成true,則將阻止這一行為,從而保留所有的棧內容。
clearTaskOnLaunch:根activity的這個屬性設置成true時,和上面的alwaysRetainTaskStat 的屬性為true情況搞好相反。
finishOnTaskLaunch:對于任何activity,如果它的這個屬性設置成true,則當task被放置到后臺,然后重新啟動后,該activity將不存在了。