喜聞樂見之Activity的launchMode

Activity的launchMode

launchMode集币,通俗點(diǎn)說,就是定義了Activity應(yīng)該如何被launch的。那么這幾種模式的區(qū)別以及應(yīng)用場(chǎng)景崔慧,會(huì)有何不同呢?谷歌是基于什么原因設(shè)計(jì)這幾種模式的呢穴墅?這幾種模式背后的工作原理是什么呢惶室?

任務(wù)和返回棧

在講解launchMode之前,先說說任務(wù)(Task)和返回棧(Back Stack玄货,有些譯作回退棧拇涤、任務(wù)棧)這兩個(gè)概念。

A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack—the back stack—in the order in which each activity is opened.

任務(wù)是指當(dāng)完成一個(gè)特定的工作時(shí)與用戶交互的一系列Activity誉结。這些Activity按照打開的順序存放在一個(gè)棧中鹅士,即返回棧。

通過定義可以知道惩坑,Activity會(huì)被按照打開的順序存放掉盅。不難猜想,這種存放方式以舒,是為了方便回退操作趾痘,也就不難解釋為什么要用棧去存放。

當(dāng)用戶點(diǎn)擊啟動(dòng)app的時(shí)候蔓钟,這個(gè)app的返回棧就會(huì)跑到前臺(tái)永票,如果這個(gè)返回棧不存在的話,就會(huì)創(chuàng)建一個(gè)滥沫。當(dāng)前Activity啟動(dòng)另一個(gè)Activity的時(shí)候侣集,新的Activity就會(huì)入棧,在棧頂兰绣。如果用戶點(diǎn)擊返回按鈕世分,當(dāng)前的Activity就會(huì)出棧并銷毀,之前的Activity就會(huì)被resume缀辩,如果棧為空臭埋,就會(huì)被銷毀掉踪央。棧中的Activity永遠(yuǎn)都不會(huì)被重新排序。

返回棧根據(jù)是否在前臺(tái)瓢阴,可以分為在前臺(tái)顯示的返回棧畅蹂,和置于后臺(tái)的返回棧。其中荣恐,置于后臺(tái)的返回棧中所有的Activity都處于stop狀態(tài)魁莉,用戶可以手動(dòng)的去切換前后臺(tái)的返回棧狀態(tài)。

當(dāng)系統(tǒng)內(nèi)存不足時(shí)募胃,系統(tǒng)會(huì)優(yōu)先銷毀處于后臺(tái)的Activity旗唁。那么問題來了。后臺(tái)銷毀Activity的優(yōu)先級(jí)是怎樣的呢痹束?是將一個(gè)返回棧中的Activity都銷毀了過后检疫,再去銷毀另一個(gè),還是說祷嘶,只是單純的按照Activity來銷毀回收呢屎媳?

任務(wù)管理

任務(wù)以及返回棧的管理,可以通過一系列的參數(shù)設(shè)置來進(jìn)行论巍,包括我們本文講解的launchMode烛谊,也是任務(wù)管理的一種方式。

taskAffinity

TaskAffinity即任務(wù)相關(guān)性嘉汰,標(biāo)識(shí)一個(gè)Activity所需要的返回棧的名字丹禀。默認(rèn)情況下是包名。設(shè)置了相同taskAffinity屬性的Activity會(huì)被放進(jìn)同一個(gè)棧中鞋怀。一個(gè)返回棧的相關(guān)性(affinity)是由這個(gè)棧的根Activity的相關(guān)性(affinity)決定的双泪。

taskAffinity屬性主要與singleTask或allowTaskReparenting結(jié)合使用,在其他情況下密似,這個(gè)屬性沒有作用焙矛。這是為什么呢?

allowTaskReparenting

它的主要作用是Activity的遷移残腌,從一個(gè)棧遷移到另一個(gè)棧村斟,這個(gè)遷移跟Activity的taskAffinity有關(guān)。

clearTaskOnLaunch

這個(gè)屬性用來清除回退棧中除了根Activity的所有Activity抛猫,只對(duì)根Activity起作用蟆盹。當(dāng)設(shè)置為true時(shí),每次重新進(jìn)入app邑滨,只會(huì)看到根Activity日缨。

finishOnTaskLaunch

這個(gè)屬性與clearTaskOnLaunch相反,它是將本Activity移除出去掖看,而不影響其他的Activity匣距。

alwaysRetainTaskState

這個(gè)屬性的作用是保存返回棧的狀態(tài),只對(duì)根Activity起作用哎壳。正常情況下毅待,系統(tǒng)清理一個(gè)返回棧,會(huì)將根Activity之上的所有Activity都清除掉归榕。設(shè)置該屬性后尸红,系統(tǒng)會(huì)保存當(dāng)前的狀態(tài)。

啟動(dòng)模式

啟動(dòng)模式主要的作用是什么呢刹泄?根據(jù)上面對(duì)任務(wù)及返回棧的介紹外里,它的作用是定義,一個(gè)新的Activity實(shí)例如何與當(dāng)前的任務(wù)相關(guān)聯(lián)特石。它本身是任務(wù)的管理方式盅蝗。

啟動(dòng)模式有兩種定義方式,manifest里定義和intent flag的方式姆蘸。一種是類似配置式的墩莫,一種是代碼層面的〕逊螅可以大致推測(cè)狂秦,肯定是帶么層面的優(yōu)先級(jí)高一些,但是代碼方式劣處就是不啟動(dòng)Activity就無(wú)法設(shè)置推捐。Android中這種一般提供動(dòng)態(tài)以及靜態(tài)方式的裂问,套路都大致相同,一些區(qū)別各種優(yōu)劣等牛柒。

其中manifest設(shè)置與intent flag中都包含對(duì)方?jīng)]有的方式愕秫。這也是兩者的一個(gè)區(qū)別。

launchMode

此處的launchMode專指Activity的launchMode屬性焰络。其中有四種方式戴甩,這四種方式想必大家也都很清楚了,在這里我不詳細(xì)展開了闪彼。

standard

最常見的一種模式甜孤,Activity的默認(rèn)模式,每次啟動(dòng)該模式的Activity畏腕,都會(huì)被重新創(chuàng)建缴川,可以從屬不同的任務(wù),也可以在一個(gè)任務(wù)中被創(chuàng)建多次描馅。

它的應(yīng)用場(chǎng)景特別廣泛把夸, 一般不是特殊需求的話,都會(huì)去使用這種模式铭污。

singleTop

如果在當(dāng)前任務(wù)的棧頂恋日,系統(tǒng)會(huì)調(diào)用Activity的onNewIntent()方法而不是重新創(chuàng)建一個(gè)新的實(shí)例膀篮。當(dāng)用戶點(diǎn)擊返回鍵時(shí),當(dāng)前Activity會(huì)被出棧岂膳,而不是會(huì)退到onNewIntent()之前的狀態(tài)誓竿。

它的應(yīng)用場(chǎng)景也有一些。例如搜索頁(yè)面谈截,每次打開筷屡,搜索一些結(jié)果,點(diǎn)擊詳情頁(yè)面簸喂,然后繼續(xù)搜索毙死。在比方說,通過通知打開的頁(yè)面喻鳄,如果該頁(yè)面存在扼倘,則更新,如果不存在诽表,則創(chuàng)建唉锌。

singleTask

該模式只允許系統(tǒng)中存在一個(gè)該Activity的實(shí)例,如果當(dāng)前實(shí)例不存在竿奏,則創(chuàng)建袄简,如果已經(jīng)存在,則將該實(shí)例之上的Activity全部出棧泛啸,走onNewIntent()绿语。

singleTask適合作為程序入口點(diǎn),當(dāng)通過其他方式調(diào)用app時(shí)候候址,不會(huì)反復(fù)創(chuàng)建主頁(yè)面吕粹。例如一般情況下的MainActivity,其他app調(diào)用的時(shí)候岗仑。

singleInstance

這種模式與singleTask十分類似匹耕,區(qū)別在于,持有該Activity的任務(wù)中只能包含一個(gè)Activity即它本身荠雕。

singleInstance適合需要與程序分離開的頁(yè)面稳其,例如鬧鐘的響鈴界面,與鬧鐘的設(shè)置相分離炸卑。再例如系統(tǒng)的撥號(hào)界面既鞠。

Intent flags

此處討論的是通過代碼方式進(jìn)行設(shè)置,常見的有如下三種方式盖文。

FLAG_ACTIVITY_NEW_TASK

使用一個(gè)新的返回棧來啟動(dòng)Activity嘱蛋,跟上面討論的singleTask類似

FLAG_ACTIVITY_SINGLE_TOP

跟上面討論的singleTop類似

FLAG_ACTIVITY_CLEAR_TOP

這種方式是上面討論的launchMode中不存在的,它與singleTop的區(qū)別是,當(dāng)已存在該實(shí)例了洒敏,會(huì)將它之上的Activity都出棧龄恋。

它經(jīng)常與FLAG_ACTIVITY_NEW_TASK組合使用,可以達(dá)到singleTask的作用桐玻。

回到問題

幾種模式的區(qū)別以及應(yīng)用場(chǎng)景篙挽,會(huì)有何不同呢荆萤?

答案見上面關(guān)于launchMode

谷歌是基于什么原因設(shè)計(jì)這幾種模式的呢镊靴?

關(guān)于這個(gè)問題,我們先倒著來推理链韭,即從使用場(chǎng)景去考慮偏竟,一般狀況下,我們打開一個(gè)頁(yè)面敞峭,不在意是否是唯一踊谋,這個(gè)是最常見的需求,因此有了standard模式旋讹,這種也是默認(rèn)的模式殖蚕。當(dāng)我們用搜索頁(yè)面,當(dāng)最頂層是搜索頁(yè)面的時(shí)候沉迹,我不希望再打開一個(gè)搜索頁(yè)面睦疫,于是有了singleTop模式。當(dāng)從其他App調(diào)用我們的app的時(shí)候鞭呕,我只希望只顯示一個(gè)主頁(yè)面時(shí)蛤育,于是有了singleTask。關(guān)于singleInstance模式葫松,則是希望與當(dāng)前的頁(yè)面分離。

但是,我覺得谷歌并不能列舉出所有的場(chǎng)景祝懂,例如腾么,我希望打開一個(gè)頁(yè)面,記錄當(dāng)前的路徑珊擂,例如a->b->c圣勒,這種場(chǎng)景下,四種模式里面沒有包含未玻。

如果從正面去推導(dǎo)的話灾而,幾種啟動(dòng)模式是任務(wù)及返回棧的管理。根據(jù)在棧中的狀態(tài)扳剿,大致可以分為如下幾類:

  1. 最常見的出棧入棧(standard)
  2. 當(dāng)前棧中唯一(singleTask)
  3. 全局唯一(singleInstance)
  4. 棧頂唯一(singleTop)

是不是很明晰了旁趟,有沒有其他的出現(xiàn)形式?肯定有的,例如棧底唯一锡搜,棧中唯一橙困。但是這種方式可以等同于當(dāng)前棧中唯一啊。

我們是否可以推導(dǎo)出耕餐,谷歌是根據(jù)唯一性凡傅,來將啟動(dòng)模式分為這幾種呢?intent flags則作為輔助的一些操作肠缔,例如部分出棧等等夏跷。當(dāng)然這些也只是我的推測(cè),不一定準(zhǔn)確明未,哈哈槽华。

這幾種模式背后的工作原理是什么呢?

見任務(wù)及返回棧

內(nèi)存回收的方式趟妥,是以Activity還是以任務(wù)作為基準(zhǔn)回收猫态?

目前已知的狀況時(shí),如果返回棧置于后臺(tái)披摄,當(dāng)內(nèi)存不足的時(shí)候亲雪,如果不設(shè)置alwaysRetainTaskState屬性的話,會(huì)將除了根Activity的所有Activity銷毀掉疚膊∫逶可以確定是以返回棧為基準(zhǔn)來進(jìn)行回收。

taskAffinity屬性為什么與singleTask一起使用才生效酿联?

可以將Activity的launchMode根據(jù)是否在棧中唯一分為兩類

  1. standard终息、singleTop
  2. singleTask、singleInstance

第一類因?yàn)槠湮ㄒ恍哉耆茫隙ㄊ桥ctaskAffinity不兼容的周崭。singleInstance創(chuàng)建的棧中只能包含本身,默認(rèn)情況下都會(huì)單獨(dú)創(chuàng)建一個(gè)棧喳张,指定與否都會(huì)單獨(dú)創(chuàng)建续镇,因此設(shè)置沒有意義。而singleTask則是當(dāng)前棧中唯一销部,適合作為根Activity摸航,創(chuàng)建一個(gè)新的棧,這也是為什么taskAffinity只能對(duì)根Activity起作用的緣故舅桩。

最后

我寫的內(nèi)容不一定正確酱虎,一些問題的解釋也是根據(jù)我看到的資料來推到出來的,例如Activity為什么會(huì)有四種啟動(dòng)模式擂涛,如果大家有準(zhǔn)確地答案读串,希望告知。另外,文中錯(cuò)誤的地方恢暖,也希望指正排监。

最后,感謝大家的瀏覽杰捂,希望對(duì)您有所幫助舆床。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市嫁佳,隨后出現(xiàn)的幾起案子挨队,更是在濱河造成了極大的恐慌,老刑警劉巖脱拼,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瞒瘸,死亡現(xiàn)場(chǎng)離奇詭異坷备,居然都是意外死亡熄浓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門省撑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赌蔑,“玉大人,你說我怎么就攤上這事竟秫⊥薰撸” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵肥败,是天一觀的道長(zhǎng)趾浅。 經(jīng)常有香客問我,道長(zhǎng)馒稍,這世上最難降的妖魔是什么皿哨? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮纽谒,結(jié)果婚禮上证膨,老公的妹妹穿的比我還像新娘。我一直安慰自己鼓黔,他們只是感情好央勒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著澳化,像睡著了一般崔步。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上缎谷,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天井濒,我揣著相機(jī)與錄音,去河邊找鬼。 笑死眼虱,一個(gè)胖子當(dāng)著我的面吹牛喻奥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播捏悬,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼撞蚕,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了过牙?” 一聲冷哼從身側(cè)響起甥厦,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寇钉,沒想到半個(gè)月后刀疙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扫倡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年谦秧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撵溃。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疚鲤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缘挑,到底是詐尸還是另有隱情集歇,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布语淘,位于F島的核電站诲宇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏惶翻。R本人自食惡果不足惜姑蓝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望维贺。 院中可真熱鬧它掂,春花似錦、人聲如沸溯泣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)垃沦。三九已至客给,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肢簿,已是汗流浹背靶剑。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工蜻拨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人桩引。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓缎讼,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親坑匠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子血崭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容