Android原理探究:Activity任務棧Task的簡單探討

轉載請註明出處,謝謝~

http://blog.csdn.net/net_168/article/details/50958700


案例

某天上班,小明正在調試前些日子開發的支付寶應用內支付功能。當他興沖沖打開支付頁面,不小心把APP切到後臺,等返回APP時卻發現支付界面莫名其妙消失了,又發現那個支付界面又偷偷跑到了隔壁支付寶APP那邊。小明突然感覺背脊一涼,產品經理那陰冷冷的話彷彿音繞耳旁:搞定這個BUG,你只有兩個小時。可是左猜又蒙想不起個所以然,這不對呀,小明的世界觀開始出現裂隙;不行,得去請教老司機,錯了,是求助老員工。而老司機聽了小明的疑惑後色眯眯的說,這是正常的現象呀!納尼~小明的世界觀徹底的崩潰了,還能這麼玩。

AndroidtaskAffinityTask

在老司機的引路下,小明翻閱了幾篇82年的文檔壓壓驚。發現,貌似跟activity裏面的屬性taskAffinity這個東西有點關係。這裏需要科普下:taskAffinity中文翻閱“親和力”,說人話就是“Activity抱團打BOSS”;然而文檔又說明擁有相同taskAffinityActivity一般情況下會組成一個Task集合。

而這個Task幹嘛的?舉個栗子:當我們從桌面啓動了應用A,應用A裏面包含了Activity1Activity2,估計記做A1A2;如果這時又有一個應用B,擁有B1B2B3這些Activity。那麼我們可以姑且認爲他們不是一夥的:A1A2屬於一個Task,而B1B2B3屬於另外一個Task。然而谷歌設計這個Task到底有什麼不可告人的祕密呢?

帶着然並卵的疑問,小明又發現了谷歌對於Task用途的一個權威解釋:Task的引入是爲了確保Activity的啓動和退出的順序,順便來個情景分析,如果系統中Activity的順序是A1-A2-A3-B1-B2-C1-C2,那麼我們要在C應用中C2這個Activity啓動屬於B應用的B1這個Activity,那麼問題來了:

1、程序要啓動B1,但從用戶角度來看,可能是要啓動B2,因爲B1B2是兩個相關聯的Activity,且B2B1之後。那麼雖然是啓動B1,既然B2已經在運行了,那就啓動B2吧。

2、如果已經從C2跳轉到B2,那麼在B2進行”BACK”鍵回退時,是應該回到C2呢還是B1呢?

爲了解決這兩個問題,谷歌引入了Task當啓動Activity時,系統會根據ActivitytaskAffinity屬性去找對應的Task(前提是採用了IntentFlagNEW_TASK配置)。如果存在相對應的TASKB1-B2);這不是找到組織了嘛,那就強行抱團插隊到TASK的最前面,也就是A1-A2-A3-C1-C2-B1-B2,那麼B2回退時,順理成章得回到B1,也就解決了上面那兩個問題。

ActivitylaunchModeFlag

那麼什麼會影響Activity的不同Task歸屬呢?智商捉雞的小明隱隱約約想起了一直熟背的Activity四大啓動模式和一直覺得很神祕的Flag,很明顯他們都是對於分配Activity從屬哪個Task的決定性因素。小明翻閱他的開發紅寶書,記有如下內容:launchModestandardsingleTopsingleTasksingleInstance等四種模式;FlagFLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_NO_HISTORY等等等(PS:那麼多,記得下也記不住)。可是他們兩種有什麼區別麼?鬼知道呀。能用就用唄~

可是,launchModeflag是怎麼決定Task的歸屬和順序的?帶着這些疑惑,小明是茶也不思、飯也不香。於是,又從各個小道打探消息,終於找茫茫百度之間找到這麼一句話:Android關於Task的設計理念有一個簡單的原則,如果是跨Task切換,調用者是沒有權利去更改被調Task裏面的Activity的順序,除非被調用者自己聲明瞭某些屬性。

稍微翻譯一下,也就是說如果Activity順序是A1-A2-B1-B2-B3-C1-C2-C3那麼在C3中啓動B的三個Activity裏面任意一個,其結果只能是 A1-A2-C1-C2-C3-B1-B2-B3,只能是整個B棧的切換調整;而如果C3啓動C中任意的Activity的話,是可以對C中的Activity的順序進行重排的,因爲C正在與用戶交互,系統認爲當前交互的任務(Task)中切換Activity是合法的。在這個設計原則前提下,我們就很容易對各種啓動方法導致的啓動結果做出一個分析:

進行Task切換的方法有兩種,一種是在AndroidManifest.xml裏面聲明Activity自身的啓動屬性,另外一種則是啓動時爲Intent添加對應的Flag。東西比較多,小明比較懶就沒一一羅列出來。各種模式各種標識,看起來炒雞複雜~

但是,小明又發現有前輩總結了這麼一個大定律。記錄如下:雖然Activity的啓動方式繁雜,但總得來說分爲三種主要類型:第一類是爲了完成在Task之間的切換;第二類是爲了完成在當前Task改變其中的Activity的順序;最後一類則是Task在切換時內部自動重排Activity的順序。

稍微舉個例子來加深印象:

第一類:在Task之間的切換,我們可以通過在intent裏面設置FLAG_ACTIVITY_NEW_TASK來啓動Activity,很顯然,如果intent所匹配到的Activity已經存在於某個Task裏面,那麼就直接切換到這個Task;如果沒有則會創建一個新的Task來容納該Activity。或者是調用者自身就希望出現在一個新的Task裏面,例如launchModesingleInstance屬性。

第二類:在同一個Task裏面調整Activity的順序,但需要注意的是隻能調整當前Task裏面的Activity的順序,例如我們可以使用CLEAR_TOP這個flag來清楚目標Activity上面的其他Activity,或者使用NO_HISTORY使得目標Activity常駐在Task之中,或者使用launchModesingleTask來顯示類似的效果。

第三類:讓被調Task再啓動前主動重排,這個並不多用,簡單說是例如發起intent的標識爲RESET_IF_NEEDED或者在清單文件裏面使用android:clearTaskOnLauch等屬性,字面意思很清楚了,這裏就不往深講了。

回顧

經過小明風風雨雨的研究心路歷程,小明對開頭的問題作了如下分析:

1、在APP中啓動了支付頁面,但是支付頁面是從屬於另外的一個APP(也就是支付寶);所以該支付頁面一般來說也就是屬於另外一個Task,暫且把自己的APP所屬的Task記爲A、支付寶所屬的Task記爲B

1、有人告訴小明桌面其實也是一個APP,桌面頁面所在的Activity當然也是從屬於某一個Task裏面,記桌面所在的TaskC

2、此時我們可以知道Activity的順序爲B1-A1-A2-A3-C1,那麼我們從APP切回桌面時,順序應該變成A1-A2-A3-C1-B1。那麼我們如果繼續點擊我們APP的圖標,很明顯順序應該是C1-B1-A1-A2-A3,也就是C1這個支付頁面就消失了;如果不點擊APP圖標而點擊支付寶圖標,順序則是A1-A2-A3-B1-C1,很明顯現在調起來的是支付界面。

完結~小明突然覺得自己挺叼炸天的O(_)O哈哈~



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章