Android中的Activity詳解--啟動模式與任務(wù)棧

目錄

  • Activity
  • 生命周期
  • 任務(wù)棧
  • 啟動模式
  • Intent Flag
  • taskAffinity屬性

1.Activity

activity的簡單介紹就不寫了,作為最常用的四大組件之一颖对,肯定都很熟悉其基本用法了盹牧。

2.生命周期

首先溪王,是都很熟悉的一張圖,即官方介紹的Activity生命周期圖.


Activity生命周期圖

情景:打開某個(gè)應(yīng)用的的FirstActivity調(diào)用方法如下:
由于之前已經(jīng)很熟悉了,這里就簡單貼一些圖瘪匿。


Paste_Image.png

按下返回鍵:


Paste_Image.png

重新打開并按下home鍵:


Paste_Image.png

再重新打開:


Paste_Image.png

在其中打開一個(gè)DialogActivity(SecondActivity)


Paste_Image.png

按下返回:


Paste_Image.png

修改SecondAcitvity為普通Activity,依舊是上述操作:


Paste_Image.png

這里強(qiáng)調(diào)一下onSaveInstanceState(Bundle outState)方法的調(diào)用時(shí)機(jī):
當(dāng)Activity有可能被系統(tǒng)殺掉時(shí)調(diào)用,注意寻馏,一定是被系統(tǒng)殺掉棋弥,自己調(diào)用finish是不行的。
測試如下:FirstActivity啟動SecondActivity:

Paste_Image.png

如果SecondActivity是android:theme="@android:style/Theme.Dialog"那么:
Paste_Image.png

如果FirstActivity啟動SecondActivity后自己調(diào)用了finish方法:
Paste_Image.png

也就是說诚欠,只要一個(gè)Activity轉(zhuǎn)為后臺顽染,那么就會調(diào)用此方法,因?yàn)槠溆锌赡鼙幌到y(tǒng)殺掉轰绵,其中存的Bundle對象就是用來存儲數(shù)據(jù)的粉寞,這個(gè)也就是onCreate方法中Bundle對象參數(shù)savedInstanceState的由來。

3.Acitvity任務(wù)棧

一個(gè)App會包含很多個(gè)Activity左腔,多個(gè)Activity之間通過intent進(jìn)行跳轉(zhuǎn)唧垦,那么原始的Activity就是使用棧這個(gè)數(shù)據(jù)結(jié)構(gòu)來保存的。
Task
A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (theback stack), in the order in which each activity is opened.
即若干個(gè)Activity的集合的棧表示一個(gè)Task翔悠。
當(dāng)App啟動時(shí)如果不存在當(dāng)前App的任務(wù)棧就會自動創(chuàng)建一個(gè)业崖,默認(rèn)情況下一個(gè)App中的所有Activity都是放在一個(gè)Task中的,但是如果指定了特殊的啟動模式蓄愁,那么就會出現(xiàn)同一個(gè)App的Activity出現(xiàn)在不同的任務(wù)棧中的情況双炕,即會有任務(wù)棧中包含來自于不同App的Activity。

4.啟動模式

  • standard

標(biāo)準(zhǔn)模式撮抓,在不指定啟動模式的情況下都是以此種方式啟動的妇斤。每次啟動都會創(chuàng)建一個(gè)新的Activity實(shí)例,覆蓋在原有的Activity上,原有的Activity入棧站超。
測試如下:在FirstActivity中啟動FirstActivity:


Paste_Image.png

當(dāng)只有一個(gè)FirstActivity時(shí)堆棧情況:


Paste_Image.png

當(dāng)在FirstActivity中啟動FirstActivity時(shí)堆棧情況:
Paste_Image.png

這就很顯然了荸恕,任務(wù)棧中一共有兩個(gè)FirstActivity,即表示每次啟動FirstActivity都是創(chuàng)建了一個(gè)新的實(shí)例死相。
  • singleTop

此種模式下融求,Activity在啟動時(shí)會進(jìn)行判斷,如果當(dāng)前的App的棧頂?shù)腁ctivity即正在活動的Activity就是將要啟動的Activity算撮,那么就不會創(chuàng)建新的實(shí)例生宛,直接使用棧頂?shù)膶?shí)例。
測試肮柜,設(shè)置FirstActivity為此啟動模式陷舅,多次點(diǎn)擊FirstActivity中的啟動FirstActivity的按鈕查看堆棧情況:
(其實(shí)點(diǎn)擊按鈕沒有啟動新Activity的動畫就可以看出并沒有啟動新Activity)

Paste_Image.png

果然,堆棧中只有一個(gè)FirstActivity
如果我在FirstActivity中啟動了SecondActivity审洞,此時(shí)FirstActivity不就不在棧頂了么莱睁,此時(shí)我再啟動FirstActivity會怎樣呢?
測試如下:
Paste_Image.png

很好的驗(yàn)證了芒澜,只有在棧頂時(shí)仰剿,才不會創(chuàng)建新實(shí)例。
這種啟動模式很適用于接收到消息之后進(jìn)行顯示的界面撰糠,總不能每次來消息都創(chuàng)建新實(shí)例酥馍,那一次來個(gè)十幾條消息豈不是爆炸了。
在此種模式下阅酪,在不創(chuàng)建新的實(shí)例的時(shí)候旨袒,會調(diào)用onNewIntent()方法。
總結(jié):棧頂?shù)腁ctivity只會有一個(gè)實(shí)例术辐,在棧頂?shù)那闆r下重復(fù)啟動該Activity只會復(fù)用該Activity,而不會創(chuàng)建一個(gè)新的砚尽,除了棧頂?shù)腁ctivity外,其他的和standard類似辉词,每次啟動都會被創(chuàng)建一個(gè)新的實(shí)例必孤。
onNewIntent(Intent intent)方法介紹
官方解釋如下:

  • This is called for activities that set launchMode to "singleTop" in
  * their package, or if a client used the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP}
  * flag when calling {@link #startActivity}.  In either case, when the
  * activity is re-launched while at the top of the activity stack instead
  * of a new instance of the activity being started, onNewIntent() will be
  * called on the existing instance with the Intent that was used to
  * re-launch it.
  *
  * <p>An activity will always be paused before receiving a new intent, so
  * you can count on {@link #onResume} being called after this method.
  *
  * <p>Note that {@link #getIntent} still returns the original Intent.  You
  * can use {@link #setIntent} to update it to this new Intent.
  *
  * @param intent The new intent that was started for the activity.

大意就是:
對于使用singleTop啟動或Intent.FLAG_ACTIVITY_SINGLE_TOP啟動的Activity,當(dāng)該Activity被重復(fù)啟動(注意一定是re-launched瑞躺,第一次啟動時(shí)不會調(diào)用)時(shí)就會調(diào)用此方法敷搪。
且調(diào)用此方法之前會先暫停Activity也就是先調(diào)用onPause方法。
而且幢哨,即使是在新的調(diào)用產(chǎn)生后此方法被調(diào)用赡勘,但是通過getIntent方法獲取到的依舊是以前的Intent,可以通過setIntent方法設(shè)置新的Intent捞镰。
方法參數(shù)就是新傳遞的Intent.

  • singleTask

1.如果是同一個(gè)App中啟動某個(gè)設(shè)置了此模式的Activity的話闸与,如果棧中已經(jīng)存在該Activity的實(shí)例毙替,那么就會將該Activity上面的Activity清空,并將此實(shí)例放在棧頂践樱。
測試:SecondActivity啟動模式設(shè)為singleTask厂画,啟動三個(gè)Activity:

Paste_Image.png

然后在ThirdActivity中啟動SecondActivity(注意不是返回,而是啟動):
Paste_Image.png

果然拷邢,SecondActivity上的ThirdActivity被清掉了
2.如果是其他應(yīng)用的Activity啟動的本應(yīng)用中此Activity袱院,那么
- 本應(yīng)用未啟動時(shí),在另一個(gè)應(yīng)用的ActivityY中啟動SecondActivity:
Paste_Image.png

顯然瞭稼,此時(shí)這個(gè)SecondActivity是在一個(gè)單獨(dú)的任務(wù)棧中的坑填,且是處于前臺的,按下返回鍵弛姜,SecondActivity結(jié)束,返回到ActivityY妖枚。
- 本應(yīng)用已經(jīng)啟動了廷臼,在后臺運(yùn)行,任務(wù)棧中是FirstActivity和SecondActivity绝页,在另一個(gè)應(yīng)用的ActivityY中啟動此Activity荠商,此時(shí)任務(wù)棧的狀態(tài):
Paste_Image.png

兩個(gè)任務(wù)棧,每個(gè)棧中都有兩個(gè)Activity续誉。
注意莱没,此時(shí)如果按下返回鍵,會出現(xiàn)什么情況呢酷鸦,到底是返回到ActivityY饰躲,還是返回到FirstActivity?
結(jié)果如下:
Paste_Image.png

前臺Activity竟然變成了FirstActivity臼隔!繼續(xù)按下返回鍵滑废,就會返回到ActivityY寡痰,ActivityX,然后退出。
也就是說诱咏,在ActivityY啟動了SecondActivity時(shí),連帶著SecondActivity的任務(wù)棧也被帶到了前臺萤彩。
那么我不禁要問了村视,如果SecondActivity啟動模式是默認(rèn)的,會不會是此種情況呢盛正?删咱,其實(shí)按照我們前面學(xué)的,按照分析的話蛮艰,應(yīng)該是SecondActivity在ActivityY所在的App所對應(yīng)的任務(wù)棧中創(chuàng)建一個(gè)新的實(shí)例腋腮,跟原本的SecondActivity所在后臺任務(wù)棧沒有一毛錢關(guān)系雀彼。
- 本應(yīng)用已經(jīng)啟動了三個(gè)Activity,任務(wù)棧中是FirstActivity和SecondActivity和ThirdActivity即寡,此時(shí)再由ActivityY啟動:
那么稍微思考一下就可以肯定運(yùn)行結(jié)果跟上面是完全相同的徊哑,因?yàn)樵谔D(zhuǎn)到SecondActivity時(shí),其上面的Activity已經(jīng)被清空了聪富。

  • singleInstance

這個(gè)模式就很好記莺丑,以此模式啟動的Activity會存放在一個(gè)單獨(dú)的任務(wù)棧中,且只會有一個(gè)實(shí)例墩蔓。
測試:SecondActivity啟動模式設(shè)為singleInstance

  FirstActivity->SesondActivity->ThirdActivity->SecondActivity->ThirdActivity

結(jié)果:


Paste_Image.png

顯然梢莽,啟動了兩次ThirdActivity任務(wù)棧中就有兩個(gè)實(shí)例,而SecondActivity在另外一個(gè)任務(wù)棧中奸披,且只有一個(gè)昏名。

5.Intent Flag設(shè)置啟動模式

在使用Intent啟動一個(gè)Activity時(shí)可以設(shè)置啟動該Activity的啟動模式:
這個(gè)屬性有很多,大致列出幾個(gè):

  • Intent.FLAG_ACTIVITY_NEW_TASK

每個(gè)啟動的Activity都在一個(gè)新的任務(wù)棧中

  • Intent.FLAG_ACTIVITY_SINGLE_TOP

singleTop

  • Intent.FLAG_ACTIVITY_CLEAR_TOP

singleTask

  • Intent.FLAG_ACTIVITY_NO_HISTORY

用此種方式啟動的Activity阵面,在它啟動了其他Activity后轻局,會自動finish.

6.taskAffinity屬性

官方文檔介紹如下:

The task that the activity has an affinity for. Activities with the same affinity conceptually belong to the same task (to the same "application" from the user's perspective). The affinity of a task is determined by the affinity of its root activity.The affinity determines two things — the task that the activity is re-parented to and the task that will house the activity when it is launched with the FLAG_ACTIVITY_NEW_TASK flag.
By default, all activities in an application have the same affinity. You can set this attribute to group them differently, and even place activities defined in different applications within the same task. To specify that the activity does not have an affinity for any task, set it to an empty string.
If this attribute is not set, the activity inherits the affinity set for the application (see the<application>element's taskAffinity.
The name of the default affinity for an application is the package name set by the<manifest>element.
大意如下:
這個(gè)屬性表示的是一個(gè)Activity對任務(wù)棧的親和度。有相同的affinity的Activity屬于同一個(gè)Task样刷,即affinity相同的Activity會被加入同一任務(wù)棧仑扑。一個(gè)任務(wù)棧的affinity由其affinity值確定或是其根Activity的affinity確定。這個(gè)屬性決定兩件事置鼻,①Activity被re-parented時(shí)的任務(wù)棧镇饮,②以FLAG_ACTIVITY_NEW_TASK啟動的Activity所在的任務(wù)棧。
默認(rèn)情況下箕母,同一個(gè)應(yīng)用內(nèi)的所有的Activity都擁有相同的affinity储藐,你可以通過設(shè)置這個(gè)值來給Activity分組,甚至將不同應(yīng)用的Activity放在相同的任務(wù)棧中司蔬。為了表明一個(gè)Activity對任何一個(gè)任務(wù)棧都不具有親和力邑茄,那么將其設(shè)為空字符串。
如果這個(gè)值沒有設(shè)置俊啼,那么就默認(rèn)使用application標(biāo)簽下的這個(gè)值肺缕。
默認(rèn)的affinity值為manifest標(biāo)簽下設(shè)置的包名。

這樣看來的話授帕,通俗易懂的講同木,就是給每一個(gè)任務(wù)棧起個(gè)名,給每個(gè)Activity也起個(gè)名跛十,在Activity以singleTask模式啟動時(shí)彤路,就檢查有沒有跟此Activity的名相同的任務(wù)棧,有的話就將其加入其中芥映。沒有的話就按照這個(gè)Activity的名創(chuàng)建一個(gè)任務(wù)棧洲尊。
測試:在App1中設(shè)置SecondActivity的taskAffinity為“gsq.test”远豺,App2中的ActivityX的taskAffinity也設(shè)為“gsq.test”

FirstActivity->SesondActivity->home->ActivityX

任務(wù)棧信息如下:


Paste_Image.png

結(jié)果很顯然了。
測試:在上述基礎(chǔ)上坞嘀,在ActivityX中進(jìn)行跳轉(zhuǎn)到ActivityY,ActivityY不指定啟動模式和taskAffinity躯护。結(jié)果如下:


Paste_Image.png

發(fā)現(xiàn)ActivityY在gsq.test任務(wù)棧中,這是由于其啟動模式是Standard丽涩,也就是在啟動這個(gè)Activity的所在的任務(wù)任務(wù)棧中棺滞。
再將ActivityY指定啟動模式singleTask:
Paste_Image.png

這樣就沒問題了,ActivityY在一個(gè)新的任務(wù)棧中矢渊,名稱為包名继准。
這時(shí)從ActivityY跳轉(zhuǎn)到SecondActivity,那應(yīng)該是gsq.test任務(wù)棧只有SecondActivity矮男,ActivityX已經(jīng)沒有了移必。因?yàn)槠鋯幽J绞莝ingleTask,在啟動它時(shí)發(fā)現(xiàn)已經(jīng)有一個(gè)實(shí)例存在毡鉴,就把它所在的任務(wù)棧上面的Activity都清空了并將其置于棧頂避凝。

還有一點(diǎn)需要提一下,在上面眨补,F(xiàn)irstActivity是App1的lunch Activity,但是由于SecondActivity并沒有指定MAIN和LAUNCHER過濾器倒脓,故在FirstActivity跳轉(zhuǎn)到SecondActivity時(shí)撑螺,按下home鍵,再點(diǎn)開App1崎弃,回到的是FirstActivity甘晤。

大致就先寫這么多吧,好像有點(diǎn)長饲做,廢話有點(diǎn)多线婚,估計(jì)也有錯(cuò)別字,不要太在意~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末盆均,一起剝皮案震驚了整個(gè)濱河市塞弊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌泪姨,老刑警劉巖游沿,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異肮砾,居然都是意外死亡诀黍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門仗处,熙熙樓的掌柜王于貴愁眉苦臉地迎上來眯勾,“玉大人枣宫,你說我怎么就攤上這事〕曰罚” “怎么了也颤?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長模叙。 經(jīng)常有香客問我歇拆,道長,這世上最難降的妖魔是什么范咨? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任故觅,我火速辦了婚禮,結(jié)果婚禮上渠啊,老公的妹妹穿的比我還像新娘输吏。我一直安慰自己,他們只是感情好替蛉,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布贯溅。 她就那樣靜靜地躺著,像睡著了一般躲查。 火紅的嫁衣襯著肌膚如雪它浅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天镣煮,我揣著相機(jī)與錄音姐霍,去河邊找鬼。 笑死典唇,一個(gè)胖子當(dāng)著我的面吹牛镊折,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播介衔,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼恨胚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了炎咖?” 一聲冷哼從身側(cè)響起赃泡,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乘盼,沒想到半個(gè)月后急迂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蹦肴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年僚碎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阴幌。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡勺阐,死狀恐怖卷中,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情渊抽,我是刑警寧澤蟆豫,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站懒闷,受9級特大地震影響十减,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜愤估,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一帮辟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧玩焰,春花似錦由驹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至默刚,卻和暖如春甥郑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背荤西。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工壹若, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人皂冰。 一個(gè)月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像养篓,于是被迫代替她去往敵國和親秃流。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

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