? 前兩天在寫項(xiàng)目的時(shí)候突然碰到個(gè)問(wèn)題宴卖,當(dāng)用戶進(jìn)入應(yīng)用時(shí),先進(jìn)入MainActivity衔峰,如果判斷為非登陸狀態(tài)佩脊,則應(yīng)該直接跳轉(zhuǎn)到登陸頁(yè)面 ,如果在登陸界面放棄登陸垫卤,則應(yīng)該直接回到主界面威彰。這意味著在登陸界面打開(kāi)時(shí),MainActivity應(yīng)該從回退棧中彈出穴肘,而不是下壓歇盼。那個(gè)時(shí)候草草百度了一番,用Intent加Flag的方法匆匆混了過(guò)去评抚,然而新棧建立的Transition動(dòng)畫著實(shí)讓人難受(所以又回去補(bǔ)了一波動(dòng)畫的相關(guān)豹缀,然而還是沒(méi)有補(bǔ)到Activity Transition的部分-_-),今天完善各個(gè)界面的邏輯和細(xì)節(jié)的時(shí)候又想起來(lái)了這檔子事慨代,于是拋下寫到一半的代碼邢笙,準(zhǔn)備溫習(xí)一下Activity進(jìn)棧出棧的具體過(guò)程。
又逮著碼字的機(jī)會(huì)了了J坛住氮惯!
? Activity的出入棧控制主要來(lái)自于兩個(gè)地方Activity的聲明處——Manifest文件定義的屬性和Activity的開(kāi)啟者——Intent的Flag定義。下面分別看看它們都能定義哪些屬性筐骇。
Manifest
? Manifest中關(guān)于Activity棧的控制债鸡,大多數(shù)人最先接觸到的大概就是android:launchMode
的四個(gè)屬性:standard、singleTop铛纬、singleTask和singleInstance厌均,它們的意義如下:
1.standard
Activity的默認(rèn)啟動(dòng)模式,在任何情況下都直接將一個(gè)新的Activity實(shí)例入棧告唆。
2.singleTop
常用的Activity啟動(dòng)模式棺弊,當(dāng)要開(kāi)啟的Activity已在棧頂時(shí),不創(chuàng)建新的實(shí)例擒悬,但調(diào)用onNewIntent方法模她;不在棧頂時(shí),創(chuàng)建新的實(shí)例懂牧。
3.singleTask
當(dāng)Activity為該啟動(dòng)模式時(shí)侈净,會(huì)先在棧中查找是否存在該Activity實(shí)例,沒(méi)有的話會(huì)新建一個(gè)實(shí)例僧凤,這個(gè)實(shí)例所在的棧與taskAffinity屬性有關(guān)畜侦;如果當(dāng)前棧中存在該Activity實(shí)例的話,則會(huì)將該實(shí)例送到棧頂躯保,并且將其之前所有的Activity全部彈出旋膳。
4.singleInstance
當(dāng)Activity為該模式時(shí),該Activity實(shí)例會(huì)有一個(gè)獨(dú)立的棧途事,并且該棧中只會(huì)有這一個(gè)實(shí)例验懊,所有跳轉(zhuǎn)到這個(gè)Activity的進(jìn)程都會(huì)共享這一個(gè)實(shí)例。當(dāng)從這個(gè)棧切換到別的Activity時(shí)尸变,會(huì)將新的Activity壓入Activity啟動(dòng)前的棧中义图,此時(shí)再返回就會(huì)跳過(guò)這個(gè)singleInstance的Activity而回到開(kāi)始的棧。
有兩個(gè)需要注意的點(diǎn)召烂,一是被singleTask標(biāo)注的Activity已在別的進(jìn)程的Task中存在且處于棧頂時(shí)碱工,就不會(huì)在Activity調(diào)用進(jìn)程創(chuàng)建一個(gè)新實(shí)例,而是將后臺(tái)進(jìn)程的Task棧內(nèi)容壓入當(dāng)前Task棧骑晶,如下圖所示:
二是Android的棧彈出策略:在當(dāng)前Task中的Activity實(shí)例已全部彈出痛垛,就會(huì)回到該Task的上一個(gè)棧,而不是直接退回到主界面(也是因?yàn)檫@個(gè)原因讓我把LoginActivity設(shè)置為singleTask從而建一個(gè)新棧桶蛔,在onBackPress時(shí)直接回到主界面的想法落空了)匙头。
除了launchMode管控的Activity啟動(dòng)策略之外Activity還有下面幾個(gè)與返回棧相關(guān)的屬性:
android:taskAffinity = "string"
其值默認(rèn)為當(dāng)前包名,用于標(biāo)識(shí)無(wú)歸屬Activity的歸屬任務(wù)仔雷。這里的無(wú)歸屬Activity指以設(shè)置了Flag為FLAG_ACTIVITY_NEW_TASK的Intent打開(kāi)的Activity 蹂析,或者是launchMode為singleTask而當(dāng)前Task中無(wú)其實(shí)例需要新建一個(gè)實(shí)例的Activity舔示。它能夠指定上述Activity所屬的Task,或者說(shuō)設(shè)定其親緣關(guān)系电抚。這個(gè)屬性設(shè)置可以達(dá)到創(chuàng)建多個(gè)棧并改變其退出順序的效果(比如實(shí)現(xiàn)以為不可能實(shí)現(xiàn)的退出MainActivity而不退出應(yīng)用)
android:allowTaskReparenting = [true|false]
其值表示是否允許將標(biāo)注的Activity在當(dāng)前Task轉(zhuǎn)入后臺(tái)時(shí)改變其所處Task惕稻,而歸屬到taskAffinity標(biāo)注的Task中去,僅對(duì)launchMode為standard與singleTop的Activity有效蝙叛,默認(rèn)為false俺祠。一個(gè)具體的例子就是當(dāng)我們的應(yīng)用調(diào)用了一個(gè)外部瀏覽器時(shí),當(dāng)該屬性為true借帘,則打開(kāi)的web頁(yè)面將歸屬于瀏覽器蜘渣,此時(shí)退出瀏覽器后會(huì)直接回到主界面;反之肺然,該屬性為false時(shí)蔫缸,退出瀏覽器界面后將會(huì)回到原來(lái)的應(yīng)用界面。
android:clearTaskOnLaunch=["true" | "false"]
其值表示home鍵返回桌面又從桌面再次打開(kāi)應(yīng)用時(shí)际起,是否清除棧底以外的所有Activity(注意拾碌,因?yàn)長(zhǎng)auncher入口只有一個(gè),所以這里的棧指的就是MainActivity棧街望,其他棧不受影響)校翔。
android:alwaysRetainTaskState=["true" | "false"]
其值表示是否允許始終保持Task的狀態(tài)(系統(tǒng)一般會(huì)在應(yīng)用無(wú)響應(yīng)半小時(shí)后清除根Activity之外的所有Activity)。
android:finishOnTaskLaunch=["true" | "false"]
當(dāng)該值為true時(shí)它匕,標(biāo)記的Activity在棧頂展融,且應(yīng)用此時(shí)從桌面被啟動(dòng)時(shí)窖认,該Activity將被finish豫柬,(但當(dāng)Activity為根Activity時(shí)失效)。
更多相關(guān)的屬性扑浸,參見(jiàn)官方文檔:<activity>標(biāo)簽
Intent
? Intent作為Android四大組件的溝通橋梁烧给,用Action確定了響應(yīng)對(duì)象,用Category規(guī)定了響應(yīng)條件喝噪,用Data描述了請(qǐng)求數(shù)據(jù)類型础嫡,至于開(kāi)啟新組件的屬性和模式,則交給了Flag酝惧。下面是列舉出來(lái)的幾個(gè)Flag:
FLAG_ACTIVITY_NEW_TASK
根據(jù)親緣關(guān)系開(kāi)啟一個(gè)Activity榴鼎,若此時(shí)存在與其有親緣關(guān)系的棧,則在該棧中開(kāi)啟Activity,開(kāi)啟方式受launchMode約束;否則創(chuàng)建一個(gè)新棧谋减。與FLAG_ACTIVITY_MULTIPLE_TASK一起使用時(shí)贰剥,無(wú)論如何都會(huì)創(chuàng)建一個(gè)新棧。
FLAG_ACTIVITY_CLEAR_TOP
類似singleTask模式弟蚀,在開(kāi)啟已存在棧中的Activity實(shí)例時(shí)脚曾,將其推至棧頂唐全,并將其上的Activity全部出棧闽瓢,但此時(shí)“推至棧頂”這個(gè)過(guò)程實(shí)際上是連已存在的相關(guān)Activity實(shí)例也一并彈出棧接癌,而重新創(chuàng)建一個(gè)Activity實(shí)例,而不是調(diào)用NewIntent.
FLAG_ACTIVITY_CLEAR_TASK
在目標(biāo)Activity打開(kāi)前清除其所在棧內(nèi)的Activity實(shí)例扣讼,必須與FLAG_ACTIVITY_NEW_TASK一起用缺猛。
FLAG_ACTIVITY_SINGLE_TOP
效果同singleTop.
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
由此標(biāo)志開(kāi)啟的Activity所處棧不會(huì)出現(xiàn)在Recent界面,該Activity需要是這個(gè)棧的根Activity椭符,其效果與activity=excludeFromRecents = "true"一致枯夜。
FLAG_ACTIVITY_TASK_ON_HOME
由此標(biāo)識(shí)開(kāi)啟的Activity所處棧將會(huì)直接置于Home所處棧之上,也就是onBackPress時(shí)會(huì)直接退出到主界面艰山。此標(biāo)識(shí)需要同F(xiàn)LAG_ACTIVITY_NEW_TASK一同使用湖雹,并且必須保證其開(kāi)啟了一個(gè)新棧。
FLAG_ACTIVITY_NO_ANIMATION
取消Activity的Transition效果曙搬。
更多的Flag參見(jiàn):Intent
最后
講道理其實(shí)Activity的棧操作還是挺麻煩的一件事摔吏,還有很多屬性都沒(méi)有列舉出來(lái),以及startActivityForResult的一些特殊情況也并沒(méi)有總結(jié)纵装,關(guān)愛(ài)懶癌晚期患者征讲。不過(guò)上面的在正常情況下應(yīng)該是夠用了,一般的場(chǎng)景也不會(huì)太多的去關(guān)注onBackPress會(huì)返回到什么界面(至今看到同應(yīng)用多棧操作的貌似也就系統(tǒng)的Setting和WPS的多任務(wù)閱讀)橡娄,實(shí)在不行反正鏈接就在那诗箍,隨時(shí)可以回去翻,就這樣吧~
如果上面的內(nèi)容有任何錯(cuò)誤或不足挽唉,歡迎各種交流指導(dǎo)滤祖,鞠躬。
個(gè)人Github主頁(yè):Lazxy