Tasks and Back Stack
原文地址:http://docs./guide/topics/fundamentals/tasks-and-back-stack.html 翻譯:無語 @ 2012.06.07?
任務(wù)棧和返回堆棧一個(gè)應(yīng)用程序通常包含多個(gè)Activity.每個(gè)Activity都必須設(shè)計(jì)成一種特定的操作, 用戶可以通過該操作去實(shí)現(xiàn)某項(xiàng)功能,并且操作其他的Activity.例如.一個(gè)電子郵件的應(yīng)用程序可能有一個(gè)Activity,用于展現(xiàn)出新的電子郵件 列表,當(dāng)用戶選擇了一個(gè)電子郵件,就打開一個(gè)新的Activity以查看該電子郵件.
圖 3. activity A 被實(shí)例化多次,。
導(dǎo)航設(shè)計(jì) 關(guān)于 Android 中應(yīng)用程序間導(dǎo)航的詳情,,請(qǐng)參閱 Android 導(dǎo)航 設(shè)計(jì)指南. 保存Activity狀態(tài)如上所述,系統(tǒng)默認(rèn)會(huì)在Activity 停止時(shí)保存其狀態(tài).這樣,當(dāng)用戶返回時(shí),用戶的界面能與離開時(shí)顯示得一樣.不過,,你可以,也應(yīng)該使用用回調(diào)方法主動(dòng)地保存Activity的狀態(tài),以便應(yīng)對(duì)Activity被銷毀并重建的情況. 當(dāng)系統(tǒng)停止一個(gè)Activity 運(yùn)行后(比如啟動(dòng)了一個(gè)新Activity 或者Task 轉(zhuǎn)入后臺(tái)),系統(tǒng)在需要回收內(nèi)存的時(shí)候有可能會(huì)完全銷毀該Activity.這時(shí),該Activity的狀態(tài)信息將會(huì)丟失.就算這種情況發(fā)生,該 Activity 仍然會(huì)存在于Back Stack中.但是當(dāng)它回到棧頂時(shí),系統(tǒng)將必須重建它(而不是恢復(fù)).為了避免用戶工作內(nèi)容的丟失,,你應(yīng)通過實(shí)現(xiàn)Activity 的 onSaveInstanceState() 方法來主動(dòng)保存這些內(nèi)容. 關(guān)于如何保存Activity 狀態(tài)的詳情,,請(qǐng)參閱 Activities. 管理多個(gè)Task如上所述,把所有已經(jīng)啟動(dòng)的Activity 相繼放入同一個(gè)Task 中以及一個(gè)“后入先出”棧,Android 管理Task和Back Stack 的這種方式適用于大多數(shù)應(yīng)用,你也不用去管理你的Activity 如何與Task關(guān)聯(lián)及如何彈出Back Stack .不過,有時(shí)候你或許決定要改變這種普通的運(yùn)行方式.也許你想讓某個(gè)Activity啟動(dòng)一個(gè)新的Task(而不是被放入當(dāng)前Task中),或者,,你想讓 activity 啟動(dòng)時(shí)只是調(diào)出已有的某個(gè)實(shí)例(而不是在Back Stack 頂創(chuàng)建一個(gè)新的實(shí)例)或者,,你想在用戶離開Task 時(shí)只保留根Activity,而Back Stack 中的其它 Activity 都要清空,, 你能做的事情還有很多,,利用 " <activity> manifest 元素的屬性和傳入 startActivity() 的 intent 中的標(biāo)識(shí)即可。 這里,,你可以使用的 <activity> 屬性主要有:
警告: 大多數(shù)應(yīng)用不應(yīng)該改變 Activity 和 Task 默認(rèn)的工作方式,。 如果你確定有必要修改默認(rèn)方式,,請(qǐng)保持謹(jǐn)慎,并確保 Activity 在啟動(dòng)和從其它 Activity 用返回鍵返回時(shí)的可用性.請(qǐng)確保對(duì)可能與用戶預(yù)期的導(dǎo)航方式相沖突的地方進(jìn)行測(cè)試. 定義啟動(dòng)模式啟動(dòng)模式定義了一個(gè)新的Activity 實(shí)例與當(dāng)前Task 的關(guān)聯(lián)方式,。定義啟動(dòng)模式的方法有兩種: 當(dāng)你在 manifest文件中聲明一個(gè)Activity 時(shí),,可以指定它啟動(dòng)時(shí)與Task 的關(guān)聯(lián)方式。 調(diào)用 startActivity() 時(shí),,可以在 Intent 中包含一個(gè)標(biāo)識(shí),用于指明新Activity 是如何(是否)與當(dāng)前Task 相關(guān)聯(lián),。 同樣的,,如果 Activity A 啟動(dòng)了Activity B,則 Activity B 可以在 manifest 中定義它如何與當(dāng)之前的Task 關(guān)聯(lián)(如果存在的話),, 并且,,Activity A 也可以要求 Activity B 與當(dāng)前 task 的關(guān)聯(lián)關(guān)系.如果兩個(gè)Activity都定義了,則 Activity A 的請(qǐng)求(intent 中定義)會(huì)比Activity B 的定義(在 manifest 中)優(yōu)先. 注意: manifest 文件中的某些啟動(dòng)模式在 intent 標(biāo)識(shí)中并不可用,,反之亦然,,intent 中的某些模式也無法在 manifest 中定義。 配置 manifest 清單文件在manifest文件中聲明Activity 時(shí),你可以使用 <activity> 元素的 launchMode 屬性來指定Activity與Task的關(guān)系. launchMode 屬性指明了Activity啟動(dòng)Task的方式,。 launchMode 屬性可設(shè)置四種啟動(dòng)模式: "standard" (默認(rèn)模式): "每次訪問實(shí)例化新的Activity" 默認(rèn),系統(tǒng)在啟動(dòng)Activity 的Task 中創(chuàng)建一個(gè)新的Activity 實(shí)例,并且把 intent 傳送路徑指向它.該Activity 可以被實(shí)例化多次,各個(gè)實(shí)例可以屬于不同的Task,,一個(gè)Task 中也可以存在多個(gè)實(shí)例. "singleTop" "每次訪問,看棧頂元素目標(biāo)對(duì)象,是則返回,不再實(shí)例化,否則,還是實(shí)例化新的Activity." 如果Activity的一個(gè)實(shí)例已經(jīng)存在于當(dāng)前Task的棧頂,該系統(tǒng)就會(huì)使用onNewIntent()方 法通過intent 傳遞給已有實(shí)例,,而不是創(chuàng)建一個(gè)新的Activity 實(shí)例.Activity 可以被實(shí)例化多次,各個(gè)實(shí)例可以屬于不同的Task,一個(gè)Task中可以存在多個(gè)實(shí)例(但只有Back Stack的Activity 實(shí)例不是該Activity 的). 例如,,假設(shè)Task 的 Back Stack 中包含了根Activity A 和 Activities B、C,、D(順序是 A-B-C-D; D在棧頂. 這時(shí)候傳過來的是啟動(dòng)D的intent,如果D的啟動(dòng)模式是默認(rèn)的"standard",,則會(huì)啟動(dòng)一個(gè)新的實(shí)例,,棧的內(nèi)容就會(huì)變?yōu)?A-B-C-D-D.但是!!!但是,如果 D 的啟動(dòng)模式是 "singleTop",,則已有的D的實(shí)例會(huì)通過onNewIntent():接收這個(gè) intent,,因?yàn)樵搶?shí)例位于棧頂——棧中內(nèi)容仍然維持 A-B-C-D 不變.當(dāng)然,如果 intent 是要啟動(dòng) B 的,則 B 的一個(gè)新實(shí)例還是會(huì)加入棧中,即使 B 的啟動(dòng)模式是"singleTop"也是如此. 注意: 一個(gè)Activity 的新實(shí)例創(chuàng)建完畢后,,用戶可以按返回鍵返回前一個(gè)activity.但是當(dāng)Activity 已有實(shí)例正在處理剛到達(dá)的intent 時(shí),,用戶無法用返回鍵回到onNewIntent()中 intent 到來之前的Activity 狀態(tài). "singleTask" "保證activity實(shí)例化一次,單任務(wù),由此所開啟的活動(dòng)和本活動(dòng)位于同一task中" 系統(tǒng)將創(chuàng)建一個(gè)新的Task,并把Activity 實(shí)例作為根放入其中.但是,,如果Activity 已經(jīng)在其它Task 中存在實(shí)例,,則系統(tǒng)會(huì)通過調(diào)用其實(shí)例的onNewIntent() 方法把 intent傳給已有實(shí)例,而不是再創(chuàng)建一個(gè)新實(shí)例. 此 activity 同一時(shí)刻只能存在一個(gè)實(shí)例. 注意: 雖然Activity啟動(dòng)了一個(gè)新的Task,但用戶仍然可以用返回鍵返回前一個(gè)activity. "singleInstance" "保證Activity實(shí)例化一次,單實(shí)例,由此所開啟的Activity在新的task中,和本活動(dòng)id不一致." 除了系統(tǒng)不會(huì)把其它Activity 放入當(dāng)前實(shí)例所在的 Task 之外,,其它均與"singleTask"相同,Activity 總是它所在Task 的唯一成員,;它所啟動(dòng)的任何Activity 都會(huì)放入其它Task 中. 舉一個(gè)事例:Android 的瀏覽器應(yīng)用就把 web 瀏覽器Activity 聲明為總是在它自己獨(dú)立的Task 中打開——把 activity設(shè)為singleTask模 式.這意味著,如果你的應(yīng)用提交 intent 來打開 Android 的瀏覽器,則其 activity不會(huì)被放入你的應(yīng)用所在的Task 中.取而代之的是,,或是為瀏覽器啟動(dòng)一個(gè)新的Task,;或是瀏覽器已經(jīng)在后臺(tái)運(yùn)行,只要把Task 重新調(diào)入前臺(tái)來處理新 intent 就可以. 無論Activity是在一個(gè)新的Task 中啟動(dòng),還是位于其它已經(jīng)存在的Task中,,用戶總是可以返回鍵返回到前一個(gè)Activity 中.但是,,如果你啟動(dòng)了一個(gè)啟動(dòng)模式設(shè)為singleTask的 activity,且有一個(gè)后臺(tái) task 中已存在實(shí)例的話,,則這個(gè)后臺(tái) task 就會(huì)整個(gè)轉(zhuǎn)到前臺(tái).這時(shí),,當(dāng)前的Back Stack就包含了這個(gè)轉(zhuǎn)入前臺(tái)的Task 中所有的Activity,位置是在棧頂.圖4所描述的就是這一種場(chǎng)景
在manifest 文件中使用啟動(dòng)模式的詳情,請(qǐng)參閱<activity>元素文檔,其中詳細(xì)描述了launchMode屬性及其可用值. 注意: 你使用launchMode 屬性為Activity設(shè)置的模式可以被啟動(dòng)Activity的intent標(biāo)識(shí)所覆蓋,,這將在下一章節(jié)具體說明,。 使用 Intent 標(biāo)識(shí)在啟動(dòng)Activity 時(shí),你可以在傳給 startActivity() 的 intent 中包含相應(yīng)標(biāo)識(shí),用于修改Activity 與Task 的默認(rèn)關(guān)系,。這個(gè)標(biāo)識(shí)可以修改的默認(rèn)模式包括:
FLAG_ACTIVITY_CLEAR_TOP 經(jīng)常與 FLAG_ACTIVITY_NEW_TASK 結(jié)合起來一起使用.這些標(biāo)識(shí)定位在其它Task中已存在的Activity,再把它放入可以響應(yīng) intent的位置上. 注意:如果Activity 的啟動(dòng)模式配置為"standard",,它就會(huì)先被移除出棧,,再創(chuàng)建一個(gè)新的實(shí)例來處理這個(gè) intent,因?yàn)閱?dòng)模式為 "standard" 時(shí),總是會(huì)創(chuàng)建一個(gè)新的實(shí)例,。 affinities處理affinity指明Activity對(duì)于哪些Task親和力更高.默認(rèn)情況下,,同一個(gè)應(yīng)用中的所有 activity 都擁有同一個(gè)affinity 值. 因此,在同一應(yīng)用程序中的所有Acttivity都喜歡在相同的Task.不過,,你可以修改Activity 默認(rèn)的 affinity 值.不同應(yīng)用中的Activity 可以共享同一個(gè)affinity 值,同一個(gè)應(yīng)用中的Activity也可以賦予不同的Task affinity值. 你可以使用<activity>元素的taskAffinity 屬性修改Activity的affinity taskAffinity 屬性是一個(gè)字符串值,必須與<manifest> 元素定義的包名稱保證唯一性,因?yàn)橄到y(tǒng)把這個(gè)包名稱用于標(biāo)識(shí)應(yīng)用的默認(rèn)Task affinity值. 下面的兩種情況下affinity將會(huì)發(fā)揮作用:
的Activity 所在Task 中,且壓入調(diào)用者所在的Back Stack 頂棧.不過,如果傳給startActivity() 的 intent 包含了FLAG_ACTIVITY_NEW_TASK 標(biāo)識(shí),則系統(tǒng)會(huì)查找另一個(gè)Task并將新Activity 放入其中.一般情況下會(huì)新開一個(gè)任務(wù),但并非一定如此.如果一個(gè)已有Task的affinity值與新 Activity的相同,則Activity 會(huì)放入該Task.如果沒有,則會(huì)新建一個(gè)新Task.
startActivity() 的 intent 中.如果你的Activity 可以被外部應(yīng)用帶此標(biāo)識(shí)來啟動(dòng),,請(qǐng)注意用戶會(huì)用其它方式返回啟動(dòng)Task,,比如通過應(yīng)用圖標(biāo)(Task 的根 Activity 帶有一個(gè)CATEGORY_LAUNCHER intent過濾器;參閱下節(jié)#啟動(dòng)task).
提示:如果一個(gè).apk文件中包含了多個(gè)“application”,從用戶的角度來看,你可能想使用taskAffinity 屬性來分配每個(gè)“application”中 activity 的 affinity 值. 清除Back Stack如果用戶長時(shí)間離開某個(gè)Task,系統(tǒng)將會(huì)僅保留一個(gè)根Activity,而把其它Activity 都清除掉.當(dāng)用戶返回Task 時(shí),只有根Activity 會(huì)被恢復(fù).系統(tǒng)的這種行為,是因?yàn)榻?jīng)過了很長時(shí)間后,用戶是要放棄之前進(jìn)行的操作,,返回Task 是為了開始新的操作. 可以使用Activity的某些屬性來改變這種行為:
啟動(dòng)Task你可以通過發(fā)送一個(gè)指定動(dòng)作和類別為 "android.intent.action.MAIN",、category 為 "android.intent.category.LAUNCHER" 發(fā)送 intent來指定某個(gè)Activity為Task的入口,例如: <activity ... >
<intent-filter ... > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> ... </activity> 這種intent過濾器將會(huì)讓此Activity 的圖標(biāo)和標(biāo)簽作為應(yīng)用啟動(dòng)圖標(biāo)來顯示,,用戶可以啟動(dòng)此Activity,并且在之后任何時(shí)候返回其啟動(dòng)時(shí)的Task. 第二個(gè)能力非常重要.用戶必須能離開一個(gè)Task ,之后能再回來使用這個(gè)啟動(dòng)Task 的Activity.由于這個(gè)原因,標(biāo)明Activity每次都會(huì)啟動(dòng)Task的這兩種啟動(dòng)模式 "singleTask" 和 ""singleInstance"應(yīng)僅用于ACTION_MAIN 和CATEGORY_LAUNCHER過濾器的Activity才能使用.例如,如果缺少過濾器會(huì)發(fā)生怎樣的問題:某個(gè)intent啟動(dòng)了一個(gè) "singleTask" activity,并新建了一個(gè)Task,用戶在此Task中工作了一段時(shí)間.然后他按了Home鍵,Tassk 就轉(zhuǎn)入后臺(tái),,變?yōu)椴豢梢姞顟B(tài),這時(shí)用戶就無法再回到Task了,,因?yàn)樗赼pplication launcher中配置對(duì)應(yīng)的屬性. 對(duì)于那些你不希望用戶能夠返回的Activity,將<activity>元素的finishOnTaskLaunch 設(shè)置為"true" 即可.詳細(xì)請(qǐng)(參閱 #清除Back Stack) |
|