a usful blog.android
http://changeyouforever.iteye.com/blog/1160038web
android:allowTaskReparenting
用來標記Activity可否從啓動的Task移動到有着affinity的Task(當這個Task進入到前臺時)——「true」,表示能移動,「false」,表示它必須呆在啓動時呆在的那個Task裏。
若是這個特性沒有被設定,設定到<application>元素上的allowTaskReparenting特性的值會應用到Activity上。默認值爲「false」。
通常來講,當Activity啓動後,它就與啓動它的Task關聯,而且在那裏耗盡它的整個生命週期。噹噹前的Task再也不顯示時,你可使用這個特性來 強制Activity移動到有着affinity的Task中。典型用法是:把一個應用程序的Activity移到另外一個應用程序的主Task中。
例如,若是e-mail中包含一個web頁的連接,點擊它就會啓動一個Activity來顯示這個頁面。這個Activity是由Browser應用程序 定義的,可是,如今它做爲e-mail Task的一部分。若是它從新宿主到Browser Task裏,當Browser下一次進入到前臺時,它就能被看見,而且,當e-mail Task再次進入前臺時,就看不到它了。
Actvity的affinity是由taskAffinity特性定義的。Task的affinity是經過讀取根Activity的affinity 決定。所以,根據定義,根Activity老是位於相同affinity的Task裏。因爲啓動模式爲「singleTask」和 「singleInstance」的Activity只能位於Task的底部,所以,從新宿主只能限於「standard」和「singleTop」模 式。
android:alwaysRetainTaskState
用來標記Activity所在的Task的狀態是否老是由系統來保持——「true」,表示老是;「false」,表示在某種情形下容許系統恢復Task 到它的初始化狀態。默認值是「false」。這個特性只針對Task的根Activity有意義;對其它Activity來講,忽略之。
通常來講,特定的情形如當用戶從主畫面從新選擇這個Task時,系統會對這個Task進行清理(從stack中刪除位於根Activity之上的全部Activivity)。典型的狀況,當用戶有一段時間沒有訪問這個Task時也會這麼作,例如30分鐘。
然而,當這個特性設爲「true」時,用戶老是能回到這個Task的最新狀態,不管他們是如何啓動的。這很是有用,例如,像Browser應用程序,這裏有不少的狀態(例如多個打開的Tab),用戶不想丟失這些狀態。
android:clearTaskOnLaunch
用來標記是否從Task中清除全部的Activity,除了根Activity外(每當從主畫面從新啓動時)——「true」,表示老是清除至它的根 Activity,「false」表示不。默認值是「false」。這個特性只對啓動一個新的Task的Activity(根Activity)有意義; 對Task中其它的Activity忽略。
當這個值爲「true」,每次用戶從新啓動這個Task時,都會進入到它的根Activity中,無論這個Task最後在作些什麼,也無論用戶是使用 BACK仍是HOME離開的。當這個值爲「false」時,可能會在一些情形下(參考alwaysRetainTaskState特性)清除Task的 Activity,但不老是。
假設,某人從主畫面啓動了Activity P,並從那裏遷移至Activity Q。接下來用戶按下HOME,而後返回Activity P。通常,用戶可能見到的是Activity Q,由於它是P的Task中最後工做的內容。然而,若是P設定這個特性爲「true」,當用戶按下HOME並使這個Task再次進入前臺時,其上的全部的 Activity(在這裏是Q)都將被清除。所以,當返回到這個Task時,用戶只能看到P。
若是這個特性和allowTaskReparenting都設定爲「true」,那些能從新宿主的Activity會移動到共享affinity的Task中;剩下的Activity都將被拋棄,如上所述。
android:finishOnTaskLaunch
用來標記當用戶再次啓動它的Task(在主畫面選擇這個Task)時已經存在的Activity實例是否要關閉(結束)——「true」,表示應該關閉,「false」表示不關閉。默認值是「false」。
若是這個特性和allowTaskReparenting都設定爲「true」,這個特性勝出。Activity的affinity忽略。這個Activity不會從新宿主,可是會銷燬。
android:launchMode
用於指示Activity如何啓動。這裏有四種模式,與Intent對象中的Activity Flags(FLAG_ACTIVITY_*變量)共同做用,來決定Activity如何啓動來處理Intent。它們是:
"standard"
"singleTop"
"singleTask"
"singleInstance"
默認模式是「standard」。
這些模式能夠分紅兩大組別,「standard」和「singleTop」一組,「singleTask」和「singleInstance」一組。具備 「standard」和「singleTop」啓動模式的Activity能夠實例化不少次。這些實例能夠屬於任何Task而且能夠位於Activity stack的任何位置。典型的狀況是,它們會進入調用startActivity()的Task(除非Intent對象包含 FLAG_ACTIVITY_NEW_TASK標誌,在這種狀況下會選擇一個不一樣的Task——參考taskAffinity特性)。
相反的,「singleTask」和「singleInstance」只能啓動一個Task。它們老是位於Activity stack的底部。甚至,設備一次只能擁有一個Activity的實例——只有一個這樣的Task。
「standard」和「singleTop」模式只在一種狀況下有差異:每次有一個新的啓動「standard」Activity的Intent,就會 建立一個新的實例來響應這個Intent。每一個實例處理一個Intent。類似的,一個「singleTop」的Activity實例也有可能被建立來處 理新的Intent。然而,若是目標Task已經有一個存在的實例而且位於stack的頂部,那麼,這個實例就會接收到這個新的Intent(調用 onNewIntent());不會建立新的實例。在其餘狀況下——例如,若是存在的「singleTop」的Activity實例在目標Task中,但 不是在stack的頂部,或者它在一個stack的頂部,但不是在目標Task中——新的實例都會被建立並壓入stack中。
「singleTask」和「singleInstance」模式也只在一種狀況下有差異:「singleTask」Activity容許其它 Activity成爲它的Task的部分。它位於Activity stack的底部,其它Activity(必須是「standard」和「singleTop」Activity)能夠啓動加入到相同的Task中。 「singleInstance」Activity,換句話說,不容許其它Activity成爲它的Task的部分。它是Task中的惟一 Activity。若是它啓動其它的Activity,這個Activity會被放置到另外一個task中——好像Intent中包含了 FLAG_ACTIVITY_NEW_TASK標誌。
android:noHistory
用於標記當用戶從Activity上離開而且它在屏幕上再也不可見時Activity是否從Activity stack中清除並結束(調用finish()方法)——「true」,表示它應該關閉,「false」,表示不須要。默認值是「false」。
「true」值意味着Activity不會留下歷史痕跡。由於它不會在Activity stack的Task中保留,所以,用戶不能返回它。
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名。app
FLAG_ACTIVITY_BROUGHT_TO_FRONT
這個標誌通常不是由程序代碼設置的,如在launchMode中設置singleTask模式時系統幫你設定。
FLAG_ACTIVITY_CLEAR_TOP
若是設置,而且這個Activity已經在當前的Task中運行,所以,再也不是從新啓動一個這個Activity的實例,而是在這個Activity上方 的全部Activity都將關閉,而後這個Intent會做爲一個新的Intent投遞到老的Activity(如今位於頂端)中。
例如,假設一個Task中包含這些Activity:A,B,C,D。若是D調用了startActivity(),而且包含一個指向Activity B的Intent,那麼,C和D都將結束,而後B接收到這個Intent,所以,目前stack的情況是:A,B。
上例中正在運行的Activity B既能夠在onNewIntent()中接收到這個新的Intent,也能夠把本身關閉而後從新啓動來接收這個Intent。若是它的啓動模式聲明爲 「multiple」(默認值),而且你沒有在這個Intent中設置FLAG_ACTIVITY_SINGLE_TOP標誌,那麼它將關閉而後從新創 建;對於其它的啓動模式,或者在這個Intent中設置FLAG_ACTIVITY_SINGLE_TOP標誌,都將把這個Intent投遞到當前這個實 例的onNewIntent()中。
這個啓動模式還能夠與FLAG_ACTIVITY_NEW_TASK結合起來使用:用於啓動一個Task中的根Activity,它會把那個Task中任 何運行的實例帶入前臺,而後清除它直到根Activity。這很是有用,例如,當從Notification Manager處啓動一個Activity。
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
若是設置,這將在Task的Activity stack中設置一個還原點,當Task恢復時,須要清理Activity。也就是說,下一次Task帶着 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED標記進入前臺時(典型的操做是用戶在主畫面重啓它),這個Activity和它之 上的都將關閉,以致於用戶不能再返回到它們,可是能夠回到以前的Activity。
這在你的程序有分割點的時候頗有用。例如,一個e-mail應用程序可能有一個操做是查看一個附件,須要啓動圖片瀏覽Activity來顯示。這個 Activity應該做爲e-mail應用程序Task的一部分,由於這是用戶在這個Task中觸發的操做。然而,當用戶離開這個Task,而後從主畫面 選擇e-mail app,咱們可能但願回到查看的會話中,但不是查看圖片附件,由於這讓人困惑。經過在啓動圖片瀏覽時設定這個標誌,瀏覽及其它啓動的Activity在下 次用戶返回到mail程序時都將所有清除。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
若是設置,新的Activity不會在最近啓動的Activity的列表中保存。
FLAG_ACTIVITY_FORWARD_RESULT
若是設置,而且這個Intent用於從一個存在的Activity啓動一個新的Activity,那麼,這個做爲答覆目標的Activity將會傳到這個 新的Activity中。這種方式下,新的Activity能夠調用setResult(int),而且這個結果值將發送給那個做爲答覆目標的 Activity。
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
這個標誌通常不禁應用程序代碼設置,若是這個Activity是從歷史記錄裏啓動的(常按HOME鍵),那麼,系統會幫你設定。
FLAG_ACTIVITY_MULTIPLE_TASK
不要使用這個標誌,除非你本身實現了應用程序啓動器。與FLAG_ACTIVITY_NEW_TASK結合起來使用,能夠禁用把已存的Task送入前臺的 行爲。當設置時,新的Task老是會啓動來處理Intent,而無論這是是否已經有一個Task能夠處理相同的事情。
因爲默認的系統不包含圖形Task管理功能,所以,你不該該使用這個標誌,除非你提供給用戶一種方式能夠返回到已經啓動的Task。
若是FLAG_ACTIVITY_NEW_TASK標誌沒有設置,這個標誌被忽略。
FLAG_ACTIVITY_NEW_TASK
若是設置,這個Activity會成爲歷史stack中一個新Task的開始。一個Task(從啓動它的Activity到下一個Task中的 Activity)定義了用戶能夠遷移的Activity原子組。Task能夠移動到前臺和後臺;在某個特定Task中的全部Activity老是保持相 同的次序。
這個標誌通常用於呈現「啓動」類型的行爲:它們提供用戶一系列能夠單獨完成的事情,與啓動它們的Activity徹底無關。
使用這個標誌,若是正在啓動的Activity的Task已經在運行的話,那麼,新的Activity將不會啓動;代替的,當前Task會簡單的移入前臺。參考FLAG_ACTIVITY_MULTIPLE_TASK標誌,能夠禁用這一行爲。
這個標誌不能用於調用方對已經啓動的Activity請求結果。
FLAG_ACTIVITY_NO_ANIMATION
若是在Intent中設置,並傳遞給Context.startActivity()的話,這個標誌將阻止系統進入下一個Activity時應用 Acitivity遷移動畫。這並不意味着動畫將永不運行——若是另外一個Activity在啓動顯示以前,沒有指定這個標誌,那麼,動畫將被應用。這個標 志能夠很好的用於執行一連串的操做,而動畫被看做是更高一級的事件的驅動。
FLAG_ACTIVITY_NO_HISTORY
若是設置,新的Activity將再也不歷史stack中保留。用戶一離開它,這個Activity就關閉了。這也能夠經過設置noHistory特性。
FLAG_ACTIVITY_NO_USER_ACTION
若是設置,做爲新啓動的Activity進入前臺時,這個標誌將在Activity暫停以前阻止從最前方的Activity回調的onUserLeaveHint()。
典型的,一個Activity能夠依賴這個回調指明顯式的用戶動做引發的Activity移出後臺。這個回調在Activity的生命週期中標記一個合適的點,並關閉一些Notification。
若是一個Activity經過非用戶驅動的事件,如來電或鬧鐘,啓動的,這個標誌也應該傳遞給Context.startActivity,保證暫停的Activity不認爲用戶已經知曉其Notification。
FLAG_ACTIVITY_PREVIOUS_IS_TOP
If set and this intent is being used to launch a new activity from an existing one, the current activity will not be counted as the top activity for deciding whether the new intent should be delivered to the top instead of starting a new one. The previous activity will be used as the top, with the assumption being that the current activity will finish itself immediately.
FLAG_ACTIVITY_REORDER_TO_FRONT
若是在Intent中設置,並傳遞給Context.startActivity(),這個標誌將引起已經運行的Activity移動到歷史stack的頂端。
例如,假設一個Task由四個Activity組成:A,B,C,D。若是D調用startActivity()來啓動Activity B,那麼,B會移動到歷史stack的頂端,如今的次序變成A,C,D,B。若是FLAG_ACTIVITY_CLEAR_TOP標誌也設置的話,那麼這 個標誌將被忽略。
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
If set, and this activity is either being started in a new task or bringing to the top an existing task, then it will be launched as the front door of the task. This will result in the application of any affinities needed to have that task in the proper state (either moving activities to or from it), or simply resetting that task to its initial state if needed.
FLAG_ACTIVITY_SINGLE_TOP
若是設置,當這個Activity位於歷史stack的頂端運行時,再也不啓動一個新的。 post
Activity和Task動畫
以前提到的,一個Activity能夠啓動另外一個,即使是定義在不一樣應用程序中的Activity。例如,假設你想讓用戶顯示一些地方的街景。而這裏已經有一個Activity能夠作到這一點,所以,你的Activity所須要作的只是在Intent對象中添加必要的信息,並傳遞給startActivity()。地圖瀏覽將會顯示你的地圖。當用戶按下BACK鍵,你的Activity會再次出如今屏幕上。this
對於用戶來講,看起來好像是地圖瀏覽與你的Activity同樣,屬於相同的應用程序,即使是它定義在其它的應用程序裏,並運行在那個應用程序的進程裏。Android經過將這兩個Activity保存在同一個Task裏來體現這一用戶體驗。簡單來講,一個Task就是用戶體驗上的一個「應用」。它將相關的Activity組合在一塊兒,以stack的方式管理。stack中根Activity啓動Task——典型的,它就是用戶在應用程序啓動欄中選擇的Activity。位於stack頂端的Activity是當前正在運行的——可以聚焦用戶的動做。當一個Activity啓動另外一個,新的Activity進入stack;它成爲正在運行的Activity。以前的Activity仍保留在stack中。當用戶按下BACK鍵,當前的Activity從stack中退出,以前的那個成爲正在運行的Activity。spa
stack包含對象,所以,若是一個Task中有多個同一個Activity的實例時——多個地圖瀏覽,例如——stack爲每一個實例擁有一個獨立的入口。位於stack中的Activity不會從新調整,只是進入和退出。code
一個Task就是一組Activity,不是一個類或者在manifest中定義的一個元素。所以,沒有辦法爲Task設置獨立於它的Activity的屬性值。Task的值做爲總體在根Activity中設置。例如,下一個章節會討論Task的「affinity」;那個值就是從Task中的根Activity中讀取的。對象
Task中的全部Activity做爲一個單元一塊兒移動。整個Task(整個Activity stack)能夠進入前臺或者退到後臺。例如,假設當前Task中的stack中有4個Activity——3個位於當前Activity下方。用戶按下HOME鍵,進入到應用程序啓動欄,而後選擇一個新的應用程序(實際上,一個新的Task)。當前Task退到後臺,而且新Task中的根Activity會顯示出來。而後,通過一段時間後,用戶回到Home畫面,而後再次選擇前一個應用程序(前一個Task)。那個擁有4個Activity的Task會進入前臺。當用戶按下BACK鍵,屏幕不會顯示用戶剛剛離開的Activity(前一個Task的根Activity)。而是,這個stack中的頂端Activity移除,相同Task中的前一個Activity會顯示出來。blog
剛纔描述的行爲是Activity和Task的默認行爲。但有方法來徹底改變它。Task之間的關聯,和一個Task中的一個Activity行爲,受啓動Activity的Intent對象中設置的Flag和manifest文件中Activity的<activity>元素的特性值交互控制。調用者和響應者都有權決定如何發生。
核心的Intent Flag有:
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
接下來的章節將描述一些Flag和特性的用法,如何相互影響,以及在使用時的建議。
Affinity和新Task
默認狀況下,一個應用程序中的全部Activity都有affinity——也就是說,屬於同一個Task中全部Activity有一個設定。然而,每一個Activity均可以在<activity>元素的taskAffinity特性上設置單獨的值。定義在不一樣應用程序中的Activity能夠共享同一個affinity,或者定義在同一個應用程序中的Activity設置不一樣的affinity。Affinity在兩種環境下工做:Intent對象包含FLAG_ACTIVITY_NEW_TASK標誌,和Activity的allowTaskReparenting特性設置爲「true」。
FLAG_ACTIVITY_NEW_TASK:
以前描述的,一個Activity通常經過調用startActivity()啓動並加入到Task中。它同調用者同樣,進入同一個Task。然而,若是傳遞給startActivity()的Intent對象中包含FLAG_ACTIVITY_NEW_TASK時,系統會搜索一個新的Task來容納新的Activity。一般,如標誌的名字所示,是一個新的Task。然而,並非必須是。若是已經存在一個Task與新Activity的affinity相同,這個Activity就會加入到那個Task中。若是不是,啓動一個新的Task。
allowTaskReparenting:
若是一個Activity的allowTaskReparenting特性設置爲「true」,它就能從啓動的Task中移到有着相同affinity的Task(這個Task進入到前臺的時候)。例如,在一個旅遊的程序中定義了一個能夠報告選擇城市的天氣狀況的Activity。它和同一個應用程序的其它Activity同樣,有着相同的Affinity(默認的Affinity),而且它容許從新宿主。你的Activity中的一個啓動了天氣預報,所以,它初始化到和你Activity相同的Task中。然而,當旅遊應用程序下一次進入到前臺時,天氣預報那個Activity將會從新編排並在那個Task中顯示。
若是從用戶的角度出發,一個.apk文件包含多個「應用」的話,你可能但願爲關聯的Activity設置不一樣的affinity。
Launch Mode
這裏4種不一樣的啓動模式能夠設置到<activity>元素的launchMode特性上:
standard(默認模式)
singleTop
singleTask
singleInstance
這些模式有如下四點區別:
l 哪一個Task將容納響應Intent的Activity。對於「standard」和「singleTop」來講,是產生Intent的那個Task(並調用startActivity())——除非Intent對象包含FLAG_ACTIVITY_NEW_TASK。在那種狀況下,不一樣的Task將被選擇,如「Affinity和新Task」中描述的那樣。對比而言,「singleTask」和「singleInstance」指示Activity老是一個Task的根。它們定義一個Task;它們不會加入到另外一個Task中。
l 是否有多個Activity的實例。「standard」和「singleTop」能夠實例化屢次。它們能夠屬於多個Task,一個特定的Task能夠有相同Activity的多個實例。對比而言,「singleTask」和「singleInstance」只能有一個實例。由於這些Activity只能位於Task的底部,這一限制意味着在設備的某個時間,不會出現這樣Task的多個實例。
l 是否能夠在同一個Task中擁有其它的Activity。「singleInstance」Activity保持單身,在它的Task中它是僅有的Activity。若是它啓動另外一個Activity,那個Activity將會放入到不一樣的Task中,而無論它的啓動模式——好像FLAG_ACTIVITY_NEW_TASK在Intent中同樣。對於其它方面,,「singleInstance」等同於「singleTask」。其它三個模式容許多個Activity加入到這個Task中。「singleTask」Activity老是位於Task的底部,但它能夠啓動其它的Activity並放入到它的Task中。「standard」和「singleTop」的Activity能夠出如今stack的任何地方。
l 是否一個新的實例啓動來處理新的Intent。對於默認的「standard」來講,都是建立一個新的實例來響應新的Intent。每一個實例處理一個Intent。對於「singleTop」來講,若是它位於目標Task的頂端,那麼,已經存在的實例就能夠重複使用來處理這個新的Intent。若是它不在頂端,那麼它就不能重複使用。替代的,新的實例將建立來響應新的Intent,並進入到stack中。
例如,假設一個Task的Activity stack中包含根Activity A和其它Activity B,C,D,而且D位於頂端,所以,stack是A-B-C-D。有一個Intent來了,它要啓動D類型的Activity。若是D有默認的「standard」啓動模式,那麼,一個新的實例將被啓動而且stack變成A-B-C-D-D。然而,若是D的啓動模式「singleTop」,已經存在的實例將去處理新來的Intent(由於它正好處在stack的頂端),而且stack依舊是A-B-C-D。
換句話說,若是來臨的Intent是衝着B類型的,那麼,B類型的實例將被建立啓動而無論B的模式是「standard」或「singleTop」(由於B不處在stack的頂端),所以,stack將會是A-B-C-D-B。
以前提到的,設備上不會出現超過一個實例的「singleTask」或「singleInstance」Activity,所以,那個實例都將去處理全部新來的Intent。「singleInstance alimama_pid="mm_15626785_2176297_8615857"; alimama_titlecolor="3366CC"; alimama_descolor ="000000"; alimama_bgcolor="FFFFFF"; alimama_bordercolor="CCCCCC"; alimama_linkcolor="008000"; alimama_bottomcolor="FFFFFF"; alimama_anglesize="0"; alimama_bgpic="0"; alimama_icon="0"; alimama_sizecode="9999"; alimama_width=468; alimama_height=90; alimama_type=2;