> 向前面說的那樣,一個(gè)activity可以啟動(dòng)另一個(gè)activity,包括在其他應(yīng)用程序里定義的activity。假如你想讓用戶顯示一些街道地圖的位置信息,已經(jīng)存在這樣一個(gè)功能的activity了,所以你只需填好Intent信息并曾通過startActivity()方法傳遞Intent,地圖瀏覽器就會(huì)顯示地圖。當(dāng)用戶按Back鍵時(shí),會(huì)回到原來的activity。
對(duì)于用戶來說,地圖瀏覽器就像你程序的一部分一樣,盡管他是在另一個(gè)應(yīng)用程序里定義并且運(yùn)行的。Android為了良好的用戶體驗(yàn)而讓兩個(gè)activity運(yùn)行在同一個(gè)任務(wù)里。簡單地說,用戶認(rèn)為一個(gè)task就是一個(gè)“應(yīng)用程序”。應(yīng)用程序是一組相關(guān)的activity,排列在一個(gè)堆棧里。通常,堆棧里的主activity會(huì)啟動(dòng)用戶在啟動(dòng)器里選擇的那個(gè)activity。棧頂?shù)腶ctivity就是當(dāng)前運(yùn)行的,得到用戶焦點(diǎn)的。當(dāng)啟動(dòng)了另一個(gè)activity,新的activity就會(huì)到棧頂,然后運(yùn)行。上一個(gè)activity仍然留在棧里。當(dāng)用戶按返回Back鍵時(shí),當(dāng)前activity就被彈出棧,上一個(gè)activity繼續(xù)運(yùn)行。
棧里保存著很多的對(duì)象。如果一個(gè)任務(wù)有很多個(gè)activity實(shí)例例如多個(gè)地圖瀏覽器,那么棧會(huì)給每一個(gè)實(shí)例分配單獨(dú)的入口,棧里的activity實(shí)例永遠(yuǎn)不會(huì)重新分配,只會(huì)被彈進(jìn),彈出。
一個(gè)任務(wù)是整個(gè)activity的堆棧,不是指一個(gè)類或者manifest文件中的一個(gè)元素。所以不可能單獨(dú)的設(shè)置棧里的某一個(gè)activity的值。事實(shí)上軟任務(wù)的值是主activity里設(shè)定的。例如我們以后會(huì)提到的“任務(wù)的affinity”。從affinity讀取的值可以設(shè)置到任務(wù)的主activity中。 任務(wù)里的所有activity被看做一個(gè)整體。這個(gè)整理可以被拿到前臺(tái)或者放在后臺(tái)運(yùn)行。假設(shè)當(dāng)前任務(wù)有四個(gè)activity,一個(gè)正在運(yùn)行的和三個(gè)在堆棧里的。用戶按下HOME鍵后,會(huì)轉(zhuǎn)到程序觸發(fā)器里,讓用戶選擇一個(gè)新的應(yīng)用程序,實(shí)際上是一個(gè)新的任務(wù)。當(dāng)前任務(wù)轉(zhuǎn)到后臺(tái),新任務(wù)的主activity開始運(yùn)行。一段時(shí)間后,用戶又回到HOME屏,選擇啟動(dòng)剛才隱藏的任務(wù),隱藏的任務(wù)中四個(gè)activity都會(huì)轉(zhuǎn)到前臺(tái)。當(dāng)用戶按下BACK鍵時(shí),屏幕不會(huì)顯示剛剛離開的activity(上一個(gè)任務(wù)的主activity),而會(huì)顯示當(dāng)前任務(wù)中,當(dāng)前棧中的上一個(gè)activity。(即不會(huì)在任務(wù)間返回只會(huì)在activity間返回)。
上面只是說了activity和任務(wù)的默認(rèn)的行為,其實(shí)可以修改他們幾乎所有的方面。activity和任務(wù)的聯(lián)系、任務(wù)里activity的行為、被Intent對(duì)象的標(biāo)記和<activity>里的元素影響著,無論是請(qǐng)求者還是回應(yīng)者都有一定決定權(quán)。
FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_CLEAR_TOP FLAG_ACTIVITY_RESET_TASK_IF_NEEDED FLAG_ACTIVITY_SINGLE_TOP
taskAffinity launchMode allowTaskReparenting clearTaskOnLaunch alwaysRetainTaskState finishOnTaskLaunch
接下來會(huì)介紹這些標(biāo)記和屬性的作用,之間的相互影響,和使用它們時(shí)的應(yīng)考慮到的問題。
(這段很別扭) 默認(rèn)情況下,一個(gè)程序里的各個(gè)activity之間都有聯(lián)系,他們共屬于同一個(gè)任務(wù)task,然而,通過taskAffinity的<activity>屬性可以給每個(gè)activity設(shè)置個(gè)人的Affinities 。定義在不同應(yīng)用程序里的activity可以共享自己的affinities,定義在相同的程序里的activity也可以聲明不同的affinities。affinity 在兩種情況下起作用:一種是當(dāng)通過Intent啟動(dòng)的activity中包含有FLAG_ACTIVITY_NEW_TASK標(biāo)記時(shí),一種是activity的allowTaskReparenting屬性被設(shè)置成true時(shí)。
如前所述,被其他activity通過startActivity()方法啟動(dòng)的activity,他和啟動(dòng)他的前一個(gè)activity屬于同一個(gè)堆棧。然而,如果傳遞的Intent對(duì)象中被設(shè)置了FLAG_ACTIVITY_NEW_TASK標(biāo)記,那么系統(tǒng)會(huì)在一個(gè)新的任務(wù)里啟動(dòng)activity。通常,啟動(dòng)的activity就像名字那樣,是一個(gè)新的任務(wù)。然后,那不是必須的,如果已經(jīng)存在了和要啟動(dòng)的activity相同affinity的任務(wù),已存在的任務(wù)會(huì)被運(yùn)行,如果不存在才會(huì)重啟一個(gè)新的任務(wù)。
如果一個(gè)activity的allowTaskReparenting 屬性為true,那么這個(gè)activity可以從啟動(dòng)他的任務(wù)里移動(dòng)到和他擁有相同affinity的activity所在的任務(wù)里,如果那個(gè)后者的activity正在頂端運(yùn)行時(shí)。例如,假設(shè)一個(gè)activity(一個(gè)旅行程序的一部分)報(bào)告所選城市的天氣情況。這個(gè)天氣activity和程序里的其他的activity擁有相同的affinity,并且天氣activity的allowTaskReparenting屬性為true,如果程序的其中一個(gè)activity啟動(dòng)天氣報(bào)告的話,那么這個(gè)天氣報(bào)告部分將會(huì)屬于你的activity。然而,當(dāng)旅行的程序接下去運(yùn)行時(shí),報(bào)告天氣這部分會(huì)在另一個(gè)任務(wù)里顯示和運(yùn)行。
如果一個(gè)apk包含多個(gè)應(yīng)用程序,你最好分配不同的affinity給activity。
// TODO Launch modes 運(yùn)行模式 Clearing the stack 清理堆棧 Starting tasks 啟動(dòng)任務(wù)
|