目錄
- Activity
- 生命周期
- 任務(wù)棧
- 啟動模式
- Intent Flag
- taskAffinity屬性
1.Activity
activity的簡單介紹就不寫了,作為最常用的四大組件之一颖对,肯定都很熟悉其基本用法了盹牧。
2.生命周期
首先溪王,是都很熟悉的一張圖,即官方介紹的Activity生命周期圖.
情景:打開某個(gè)應(yīng)用的的FirstActivity調(diào)用方法如下:
由于之前已經(jīng)很熟悉了,這里就簡單貼一些圖瘪匿。
按下返回鍵:
重新打開并按下home鍵:
再重新打開:
在其中打開一個(gè)DialogActivity(SecondActivity)
按下返回:
修改SecondAcitvity為普通Activity,依舊是上述操作:
這里強(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:
如果SecondActivity是
android:theme="@android:style/Theme.Dialog"
那么:如果FirstActivity啟動SecondActivity后自己調(diào)用了finish方法:
也就是說诚欠,只要一個(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:
當(dāng)只有一個(gè)FirstActivity時(shí)堆棧情況:
當(dāng)在FirstActivity中啟動FirstActivity時(shí)堆棧情況:
這就很顯然了荸恕,任務(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)
果然,堆棧中只有一個(gè)FirstActivity
如果我在FirstActivity中啟動了SecondActivity审洞,此時(shí)FirstActivity不就不在棧頂了么莱睁,此時(shí)我再啟動FirstActivity會怎樣呢?
測試如下:
很好的驗(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:
然后在ThirdActivity中啟動SecondActivity(注意不是返回,而是啟動):
果然拷邢,SecondActivity上的ThirdActivity被清掉了
2.如果是其他應(yīng)用的Activity啟動的本應(yīng)用中此Activity袱院,那么
- 本應(yīng)用未啟動時(shí),在另一個(gè)應(yīng)用的ActivityY中啟動SecondActivity:
顯然瞭稼,此時(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):
兩個(gè)任務(wù)棧,每個(gè)棧中都有兩個(gè)Activity续誉。
注意莱没,此時(shí)如果按下返回鍵,會出現(xiàn)什么情況呢酷鸦,到底是返回到ActivityY饰躲,還是返回到FirstActivity?
結(jié)果如下:
前臺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é)果:
顯然梢莽,啟動了兩次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ù)棧信息如下:
結(jié)果很顯然了。
測試:在上述基礎(chǔ)上坞嘀,在ActivityX中進(jìn)行跳轉(zhuǎn)到ActivityY,ActivityY不指定啟動模式和taskAffinity躯护。結(jié)果如下:
發(fā)現(xiàn)ActivityY在gsq.test任務(wù)棧中,這是由于其啟動模式是Standard丽涩,也就是在啟動這個(gè)Activity的所在的任務(wù)任務(wù)棧中棺滞。
再將ActivityY指定啟動模式singleTask:
這樣就沒問題了,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ò)別字,不要太在意~~~