建議首先閱讀下面這篇文章,,這樣才能對(duì)本文有所了解:
Android Application Task Activities的關(guān)系
http://www.cnblogs.com/ghj1976/archive/2011/04/29/2032412.html 尤其要明白 Task 是啥。
什么是Affinity
在某些情況下,,Android需要知道一個(gè)Activity屬于哪個(gè)Task,,即使它沒有被啟動(dòng)到一個(gè)具體的Task里,。這是通過任務(wù)共用性(Affinities)完成的。任務(wù)共用性(Affinities)為這個(gè)運(yùn)行一個(gè)或多個(gè)Activity的Task提供了一個(gè)獨(dú)特的靜態(tài)名稱,,默認(rèn)的一個(gè)活動(dòng)的任務(wù)共用性(Affinity)是實(shí)現(xiàn)了該Activity的.apk包的名字,。
當(dāng)開始一個(gè)沒有Intent.FLAG_ACTIVITY_NEW_TASK標(biāo)志的Activity時(shí),任務(wù)共用性affinities不會(huì)影響將會(huì)運(yùn)行該新活動(dòng)的Task:它總是運(yùn)行在啟動(dòng)它的Task里,。但是,,如果使用了NEW_TASK標(biāo)志,那么共用性(affinity)將被用來判斷是否已經(jīng)存在一個(gè)有相同共用性(affinity)的Task,。如果是這樣,,這項(xiàng)Task將被切換到前面而新的Activity會(huì)啟動(dòng)于這個(gè)Task的頂層。
這種特性在您必須使用NEW_TASK標(biāo)志的情況下最有用,,尤其是從狀態(tài)欄通知或桌面快捷方式啟動(dòng)活動(dòng)時(shí),。結(jié)果是,當(dāng)用戶用這種方式啟動(dòng)您的應(yīng)用程序時(shí),,它的當(dāng)前Task將被切換到前臺(tái),,而且想要查看的Activity被放在最上面。
你可以在程序清單(Manifest)文件的應(yīng)用程序application標(biāo)簽中為.apk包中所有的活動(dòng)分配你自己的任務(wù)共用性Affinites,,或者在活動(dòng)標(biāo)記中為各個(gè)活動(dòng)進(jìn)行分配,。
一些說明其如何使用的例子如下:
- 如果您的.apk包含多個(gè)用戶可以啟動(dòng)的高層應(yīng)用程序,那么您可能需要對(duì)用戶看到的每個(gè)Activity(活動(dòng))指定不同的affinities,。一個(gè)不錯(cuò)的命名慣例是以附加一個(gè)以冒號(hào)分隔的字符串來擴(kuò)展您的.apk包名,。例如,“ com.android.contacts ”.apk可以有affinities:“com.android.contacts:Dialer”和“ com.android.contacts:ContactsList”,。
- 如果您正在替換一個(gè)通知,,快捷方式,或其他可以從外部發(fā)起的應(yīng)用程序的“內(nèi)部”活動(dòng),,你可能需要明確設(shè)定您替代活動(dòng)的taskAffinity和您準(zhǔn)備替代的應(yīng)用程序一樣,。例如,如果您想替換contacts詳細(xì)信息視圖(用戶可以創(chuàng)建并調(diào)用快捷方式),,你得把taskAffinity設(shè)置成“com.android.contacts”,。
在前面的文章“Android四種Activity的加載模式”我們提到:Activity的加載模式受啟動(dòng)Activity的Intent對(duì)象中設(shè)置的Flag和manifest文件中Activity的<activity>元素的特性值交互控制。
跟 Task 有關(guān)的 manifest文件中Activity的特性值介紹
android:allowTaskReparenting
用來標(biāo)記Activity能否從啟動(dòng)的Task移動(dòng)到有著affinity的Task(當(dāng)這個(gè)Task進(jìn)入到前臺(tái)時(shí))
“true”,,表示能移動(dòng),,“false”,表示它必須呆在啟動(dòng)時(shí)呆在的那個(gè)Task里,。
如果這個(gè)特性沒有被設(shè)定,,設(shè)定到<application>元素上的allowTaskReparenting特性的值會(huì)應(yīng)用到Activity上。默認(rèn)值為“false”,。
一般來說,,當(dāng)Activity啟動(dòng)后,它就與啟動(dòng)它的Task關(guān)聯(lián),,并且在那里耗盡它的整個(gè)生命周期,。當(dāng)當(dāng)前的Task不再顯示時(shí),你可以使用這個(gè)特性來強(qiáng)制Activity移動(dòng)到有著affinity的Task中,。典型用法是:把一個(gè)應(yīng)用程序的Activity移到另一個(gè)應(yīng)用程序的主Task中,。
例如,如果 email中包含一個(gè)web頁的鏈接,,點(diǎn)擊它就會(huì)啟動(dòng)一個(gè)Activity來顯示這個(gè)頁面,。這個(gè)Activity是由Browser應(yīng)用程序定義的,但是,,現(xiàn)在它作為email Task的一部分,。如果它重新宿主到Browser Task里,當(dāng)Browser下一次進(jìn)入到前臺(tái)時(shí),,它就能被看見,,并且,當(dāng)email Task再次進(jìn)入前臺(tái)時(shí),,就看不到它了,。
Actvity的affinity是由taskAffinity特性定義的。Task的affinity是通過讀取根Activity的affinity決定,。因此,,根Activity總是位于相同affinity的Task里。由于啟動(dòng)模式為“singleTask”和“singleInstance”的Activity只能位于Task的底部,,因此,,重新宿主只能限于“standard”和“singleTop”模式。
android:alwaysRetainTaskState
用來標(biāo)記Activity所在的Task的狀態(tài)是否總是由系統(tǒng)來保持,。
“true”,,表示總是;“false”,,表示在某種情形下允許系統(tǒng)恢復(fù)Task到它的初始化狀態(tài),。默認(rèn)值是“false”。
這個(gè)特性只針對(duì)Task的根Activity有意義,;對(duì)其它Activity來說,,忽略之。
一般來說,,特定的情形如當(dāng)用戶從主畫面重新選擇這個(gè)Task時(shí),,系統(tǒng)會(huì)對(duì)這個(gè)Task進(jìn)行清理(從stack中刪除位于根Activity之上的所有Activivity)。典型的情況,,當(dāng)用戶有一段時(shí)間沒有訪問這個(gè)Task時(shí)也會(huì)這么做,,例如30分鐘,。
然而,當(dāng)這個(gè)特性設(shè)為“true”時(shí),,用戶總是能回到這個(gè)Task的最新狀態(tài),,無論他們是如何啟動(dòng)的。這非常有用,,例如,,像Browser應(yīng)用程序,這里有很多的狀態(tài)(例如多個(gè)打開的Tab),,用戶不想丟失這些狀態(tài),。
android:clearTaskOnLaunch
用來標(biāo)記是否從Task中清除所有的Activity,除了根Activity外(每當(dāng)從主畫面重新啟動(dòng)時(shí))
“true”,,表示總是清除至它的根Activity,,“false”表示不。默認(rèn)值是“false”,。
這個(gè)特性只對(duì)啟動(dòng)一個(gè)新的Task的Activity(根Activity)有意義,;對(duì)Task中其它的Activity忽略。
當(dāng)這個(gè)值為“true”,,每次用戶重新啟動(dòng)這個(gè)Task時(shí),,都會(huì)進(jìn)入到它的根Activity中,不管這個(gè)Task最后在做些什么,,也不管用戶是使用BACK還是HOME離開的,。當(dāng)這個(gè)值為“false”時(shí),可能會(huì)在一些情形下(參考alwaysRetainTaskState特性)清除Task的Activity,,但不總是,。
假設(shè),某人從主畫面啟動(dòng)了Activity P,,并從那里遷移至Activity Q,。接下來用戶按下HOME,然后返回Activity P,。一般,,用戶可能見到的是Activity Q,因?yàn)樗荘的Task中最后工作的內(nèi)容,。然而,,如果P設(shè)定這個(gè)特性為“true”,當(dāng)用戶按下HOME并使這個(gè)Task再次進(jìn)入前臺(tái)時(shí),,其上的所有的Activity(在這里是Q)都將被清除,。因此,當(dāng)返回到這個(gè)Task時(shí),用戶只能看到P,。
如果這個(gè)特性和allowTaskReparenting都設(shè)定為“true”,,那些能重新宿主的Activity會(huì)移動(dòng)到共享affinity的Task中;剩下的Activity都將被拋棄,,如上所述,。
android:finishOnTaskLaunch
用來標(biāo)記當(dāng)用戶再次啟動(dòng)它的Task(在主畫面選擇這個(gè)Task)時(shí)已經(jīng)存在的Activity實(shí)例是否要關(guān)閉(結(jié)束)
“true”,,表示應(yīng)該關(guān)閉,,“false”表示不關(guān)閉。默認(rèn)值是“false”,。
如果這個(gè)特性和allowTaskReparenting都設(shè)定為“true”,,這個(gè)特性勝出。Activity的affinity忽略,。這個(gè)Activity不會(huì)重新宿主,,但是會(huì)銷毀。
android:launchMode
用于指示Activity如何啟動(dòng),。這里有四種模式,,與Intent對(duì)象中的Activity Flags(FLAG_ACTIVITY_*變量)共同作用,來決定Activity如何啟動(dòng)來處理Intent,。它們是:
"standard"
"singleTop"
"singleTask"
"singleInstance"
默認(rèn)模式是“standard”,。
前面文章:“Android四種Activity的加載模式”已經(jīng)詳細(xì)描述,這里就不做描述了.
android:noHistory
用于標(biāo)記當(dāng)用戶從Activity上離開并且它在屏幕上不再可見時(shí)Activity是否從Activity stack中清除并結(jié)束(調(diào)用finish()方法)——“true”,表示它應(yīng)該關(guān)閉,,“false”,,表示不需要。默認(rèn)值是“false”,。
“true”值意味著Activity不會(huì)留下歷史痕跡,。因?yàn)樗粫?huì)在Activity stack的Task中保留,因此,,用戶不能返回它,。
比如啟用界面的就可以借用這個(gè)。
android:taskAffinity
這就是本文所描述的任務(wù)共用性,。
Activity為Task擁有的一個(gè)affinity,。擁有相同的affinity的Activity理論上屬于相同的Task(在用戶的角度是相同的“應(yīng)用程序”)。Task的affinity是由它的根Activity決定的,。
affinity決定兩件事情——Activity重新宿主的Task(參考allowTaskReparenting特性)和使用FLAG_ACTIVITY_NEW_TASK標(biāo)志啟動(dòng)的Activity宿主的Task,。
默認(rèn)情況,一個(gè)應(yīng)用程序中的所有Activity都擁有相同的affinity,。捏可以設(shè)定這個(gè)特性來重組它們,,甚至可以把不同應(yīng)用程序中定義的Activity放置到相同的Task中。為了明確Activity不宿主特定的Task,設(shè)定該特性為空的字符串,。
如果這個(gè)特性沒有設(shè)置,,Activity將從應(yīng)用程序的設(shè)定那里繼承下來(參考<application>元素的taskAffinity特性)。應(yīng)用程序默認(rèn)的affinity的名字是<manifest>元素中設(shè)定的package名,。
跟 Task 有關(guān)的 Intent對(duì)象中設(shè)置的Flag
FLAG_ACTIVITY_BROUGHT_TO_FRONT
這個(gè)標(biāo)志一般不是由程序代碼設(shè)置的,,如在launchMode中設(shè)置singleTask模式時(shí)系統(tǒng)幫你設(shè)定。
FLAG_ACTIVITY_CLEAR_TOP
如果設(shè)置,,并且這個(gè)Activity已經(jīng)在當(dāng)前的Task中運(yùn)行,,因此,不再是重新啟動(dòng)一個(gè)這個(gè)Activity的實(shí)例,,而是在這個(gè)Activity上方的所有Activity都將關(guān)閉,,然后這個(gè)Intent會(huì)作為一個(gè)新的Intent投遞到老的Activity(現(xiàn)在位于頂端)中。
例如,,假設(shè)一個(gè)Task中包含這些Activity:A,,B,C,,D,。如果D調(diào)用了startActivity(),并且包含一個(gè)指向Activity B的Intent,,那么,,C和D都將結(jié)束,然后B接收到這個(gè)Intent,,因此,,目前stack的狀況是:A,B,。
上例中正在運(yùn)行的Activity B既可以在onNewIntent()中接收到這個(gè)新的Intent,,也可以把自己關(guān)閉然后重新啟動(dòng)來接收這個(gè)Intent。如果它的啟動(dòng)模式聲明為“multiple”(默認(rèn)值),,并且你沒有在這個(gè)Intent中設(shè)置FLAG_ACTIVITY_SINGLE_TOP標(biāo)志,,那么它將關(guān)閉然后重新創(chuàng)建;對(duì)于其它的啟動(dòng)模式,,或者在這個(gè)Intent中設(shè)置FLAG_ACTIVITY_SINGLE_TOP標(biāo)志,,都將把這個(gè)Intent投遞到當(dāng)前這個(gè)實(shí)例的onNewIntent()中。
這個(gè)啟動(dòng)模式還可以與FLAG_ACTIVITY_NEW_TASK結(jié)合起來使用:用于啟動(dòng)一個(gè)Task中的根Activity,,它會(huì)把那個(gè)Task中任何運(yùn)行的實(shí)例帶入前臺(tái),,然后清除它直到根Activity。這非常有用,,例如,,當(dāng)從Notification Manager處啟動(dòng)一個(gè)Activity。
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
如果設(shè)置,這將在Task的Activity stack中設(shè)置一個(gè)還原點(diǎn),,當(dāng)Task恢復(fù)時(shí),,需要清理Activity。也就是說,,下一次Task帶著FLAG_ACTIVITY_RESET_TASK_IF_NEEDED標(biāo)記進(jìn)入前臺(tái)時(shí)(典型的操作是用戶在主畫面重啟它),,這個(gè)Activity和它之上的都將關(guān)閉,以至于用戶不能再返回到它們,,但是可以回到之前的Activity,。
這在你的程序有分割點(diǎn)的時(shí)候很有用。例如,,一個(gè)e-mail應(yīng)用程序可能有一個(gè)操作是查看一個(gè)附件,,需要啟動(dòng)圖片瀏覽Activity來顯示,。這個(gè)Activity應(yīng)該作為e-mail應(yīng)用程序Task的一部分,,因?yàn)檫@是用戶在這個(gè)Task中觸發(fā)的操作。然而,,當(dāng)用戶離開這個(gè)Task,,然后從主畫面選擇e-mail app,我們可能希望回到查看的會(huì)話中,,但不是查看圖片附件,,因?yàn)檫@讓人困惑。通過在啟動(dòng)圖片瀏覽時(shí)設(shè)定這個(gè)標(biāo)志,,瀏覽及其它啟動(dòng)的Activity在下次用戶返回到mail程序時(shí)都將全部清除,。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
如果設(shè)置,新的Activity不會(huì)在最近啟動(dòng)的Activity的列表中保存,。
FLAG_ACTIVITY_FORWARD_RESULT
如果設(shè)置,,并且這個(gè)Intent用于從一個(gè)存在的Activity啟動(dòng)一個(gè)新的Activity,那么,,這個(gè)作為答復(fù)目標(biāo)的Activity將會(huì)傳到這個(gè)新的Activity中,。這種方式下,新的Activity可以調(diào)用setResult(int),,并且這個(gè)結(jié)果值將發(fā)送給那個(gè)作為答復(fù)目標(biāo)的Activity,。
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
這個(gè)標(biāo)志一般不由應(yīng)用程序代碼設(shè)置,如果這個(gè)Activity是從歷史記錄里啟動(dòng)的(常按HOME鍵),,那么,,系統(tǒng)會(huì)幫你設(shè)定。
FLAG_ACTIVITY_MULTIPLE_TASK
不要使用這個(gè)標(biāo)志,,除非你自己實(shí)現(xiàn)了應(yīng)用程序啟動(dòng)器,。與FLAG_ACTIVITY_NEW_TASK結(jié)合起來使用,可以禁用把已存的Task送入前臺(tái)的行為。當(dāng)設(shè)置時(shí),,新的Task總是會(huì)啟動(dòng)來處理Intent,,而不管這是是否已經(jīng)有一個(gè)Task可以處理相同的事情。
由于默認(rèn)的系統(tǒng)不包含圖形Task管理功能,,因此,,你不應(yīng)該使用這個(gè)標(biāo)志,除非你提供給用戶一種方式可以返回到已經(jīng)啟動(dòng)的Task,。
如果FLAG_ACTIVITY_NEW_TASK標(biāo)志沒有設(shè)置,,這個(gè)標(biāo)志被忽略。
FLAG_ACTIVITY_NEW_TASK
如果設(shè)置,,這個(gè)Activity會(huì)成為歷史stack中一個(gè)新Task的開始,。一個(gè)Task(從啟動(dòng)它的Activity到下一個(gè)Task中的Activity)定義了用戶可以遷移的Activity原子組。Task可以移動(dòng)到前臺(tái)和后臺(tái),;在某個(gè)特定Task中的所有Activity總是保持相同的次序,。
這個(gè)標(biāo)志一般用于呈現(xiàn)“啟動(dòng)”類型的行為:它們提供用戶一系列可以單獨(dú)完成的事情,與啟動(dòng)它們的Activity完全無關(guān),。
使用這個(gè)標(biāo)志,,如果正在啟動(dòng)的Activity的Task已經(jīng)在運(yùn)行的話,那么,,新的Activity將不會(huì)啟動(dòng),;代替的,當(dāng)前Task會(huì)簡單的移入前臺(tái),。參考FLAG_ACTIVITY_MULTIPLE_TASK標(biāo)志,,可以禁用這一行為。
這個(gè)標(biāo)志不能用于調(diào)用方對(duì)已經(jīng)啟動(dòng)的Activity請(qǐng)求結(jié)果,。
FLAG_ACTIVITY_NO_ANIMATION
如果在Intent中設(shè)置,,并傳遞給Context.startActivity()的話,這個(gè)標(biāo)志將阻止系統(tǒng)進(jìn)入下一個(gè)Activity時(shí)應(yīng)用Acitivity遷移動(dòng)畫,。這并不意味著動(dòng)畫將永不運(yùn)行——如果另一個(gè)Activity在啟動(dòng)顯示之前,,沒有指定這個(gè)標(biāo)志,那么,,動(dòng)畫將被應(yīng)用,。這個(gè)標(biāo)志可以很好的用于執(zhí)行一連串的操作,而動(dòng)畫被看作是更高一級(jí)的事件的驅(qū)動(dòng),。
FLAG_ACTIVITY_NO_HISTORY
如果設(shè)置,,新的Activity將不再歷史stack中保留。用戶一離開它,,這個(gè)Activity就關(guān)閉了,。這也可以通過設(shè)置noHistory特性,。
FLAG_ACTIVITY_NO_USER_ACTION
如果設(shè)置,作為新啟動(dòng)的Activity進(jìn)入前臺(tái)時(shí),,這個(gè)標(biāo)志將在Activity暫停之前阻止從最前方的Activity回調(diào)的onUserLeaveHint(),。
典型的,一個(gè)Activity可以依賴這個(gè)回調(diào)指明顯式的用戶動(dòng)作引起的Activity移出后臺(tái),。這個(gè)回調(diào)在Activity的生命周期中標(biāo)記一個(gè)合適的點(diǎn),,并關(guān)閉一些Notification。
如果一個(gè)Activity通過非用戶驅(qū)動(dòng)的事件,,如來電或鬧鐘,,啟動(dòng)的,這個(gè)標(biāo)志也應(yīng)該傳遞給Context.startActivity,,保證暫停的Activity不認(rèn)為用戶已經(jīng)知曉其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中設(shè)置,并傳遞給Context.startActivity(),,這個(gè)標(biāo)志將引發(fā)已經(jīng)運(yùn)行的Activity移動(dòng)到歷史stack的頂端,。
例如,假設(shè)一個(gè)Task由四個(gè)Activity組成:A,B,C,D,。如果D調(diào)用startActivity()來啟動(dòng)Activity B,,那么,B會(huì)移動(dòng)到歷史stack的頂端,,現(xiàn)在的次序變成A,C,D,B。如果FLAG_ACTIVITY_CLEAR_TOP標(biāo)志也設(shè)置的話,,那么這個(gè)標(biāo)志將被忽略,。
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
如果設(shè)置,當(dāng)這個(gè)Activity位于歷史stack的頂端運(yùn)行時(shí),,不再啟動(dòng)一個(gè)新的,。
參考資料:
Android應(yīng)用程序模型:應(yīng)用程序,任務(wù),,進(jìn)程和線程
http://blog.csdn.net/iefreer/archive/2009/08/18/4460196.aspx
Task和Activity相關(guān)
http://chengbs./blog/798810