本篇博客是筆者看過(guò)《Android開(kāi)發(fā)藝術(shù)探索》才寫(xiě)的茧痕,有些是借鑒了此本書(shū)的內(nèi)容晤碘,當(dāng)有些內(nèi)容進(jìn)行了精進(jìn)。
Activity生命周期和啟動(dòng)模式
1.Activity的生命周期全面分析
1.1 典型情況下的Activty生命周期分析
??典型情況下的Activity的生命周期在基礎(chǔ)階段你已經(jīng)學(xué)過(guò)啦,碍遍,我們?cè)賮?lái)回顧一次奖磁,這次就整清楚些改基,把Activity生命周期的每一個(gè)過(guò)程弄清楚:
1.啟動(dòng)了一個(gè)Activity,通常是Intent來(lái)完成。啟動(dòng)一個(gè)Activity首先要執(zhí)行的回調(diào)函數(shù)是onCreate(),通常在代碼中你需要在此函數(shù)中綁定布局咖为,綁定控件秕狰,初始化數(shù)據(jù)等做一些初始化的工作稠腊。
2.即將執(zhí)行Activity的onStart()函數(shù),執(zhí)行之后Activity已經(jīng)可見(jiàn)鸣哀,但是還沒(méi)有出現(xiàn)在前臺(tái)架忌,無(wú)法與用戶進(jìn)行交互。這個(gè)時(shí)候通常Activity已經(jīng)在后臺(tái)準(zhǔn)備好了我衬,但是就差執(zhí)行onResume()函數(shù)出現(xiàn)在前臺(tái)叹放。
3.即將執(zhí)行Activity的onResume()函數(shù),執(zhí)行之后Activity不止可見(jiàn)而且還會(huì)出現(xiàn)在前臺(tái)挠羔,可以與用戶進(jìn)行交互啦井仰。
4.由于Activity執(zhí)行了onResume()函數(shù),所以Activity出現(xiàn)在了前臺(tái)破加。也就是Activity處于運(yùn)行狀態(tài)俱恶。
5.處于運(yùn)行狀態(tài)的Activity即將執(zhí)行onPause()函數(shù),什么情況下促使Activity執(zhí)行onPause()方法呢范舀?
?[1]啟動(dòng)了一個(gè)新的Activity
?[2]返回上一個(gè)Activity
?可以理解為當(dāng)需要其他Activity速那,當(dāng)前的Activity必須先把手頭的工作暫停下來(lái),再來(lái)把當(dāng)前的界面空間交給下一個(gè)需要界面的Activity尿背,而onPause()方法可以看作是一個(gè)轉(zhuǎn)接工作的過(guò)程端仰,因?yàn)槠聊豢臻g只有那么一個(gè),每次只允許一個(gè)Activity出現(xiàn)在前臺(tái)進(jìn)行工作田藐。通常情況下onPause()函數(shù)不會(huì)被單獨(dú)執(zhí)行荔烧,執(zhí)行完onPause()方法后會(huì)繼續(xù)執(zhí)行onStop()方法,執(zhí)行完onStop()方法才真正意味著當(dāng)前的Activity已經(jīng)退出前臺(tái)汽久,存在于后臺(tái)鹤竭。
6.Activity即將執(zhí)行onStop()函數(shù),在“5”中已經(jīng)說(shuō)得很清楚了景醇,當(dāng)Activity要從前臺(tái)切換至后臺(tái)的時(shí)候會(huì)執(zhí)行臀稚,比如:用戶點(diǎn)擊了返回鍵,或者用戶切換至其他Activity等三痰。
7.當(dāng)前的Activity即將執(zhí)行onDestory()函數(shù)吧寺,代表著這個(gè)Activity即將進(jìn)入生命的終結(jié)點(diǎn),這是Activity生命周期中的最后一次回調(diào)生命周期散劫,我們可以在onDestory()函數(shù)中稚机,進(jìn)行一些回收工作和資源的釋放工作,比如:廣播接收器的注銷(xiāo)工作等获搏。
8.執(zhí)行完onDestory()方法的Activity接下來(lái)面對(duì)的是被GC回收赖条,宣告生命終結(jié)。
9.很少情況下Activity才走“9”,網(wǎng)上一些關(guān)于對(duì)話框彈出后Activity會(huì)走“9”的說(shuō)法纬乍,經(jīng)過(guò)筆者驗(yàn)證碱茁,在某個(gè)Activity內(nèi)彈出對(duì)話框并沒(méi)有走“9”,所以網(wǎng)上大部分這樣說(shuō)法的文章要么是沒(méi)驗(yàn)證仿贬,要么直接轉(zhuǎn)載的早芭,這個(gè)例子說(shuō)明,實(shí)驗(yàn)出真知诅蝶,好了退个,不廢話了,那么什么情況下调炬,Activity會(huì)走“9”呢语盈?看看下面這位博主才是真的懂得“實(shí)驗(yàn)出真知”的人:
http://blog.csdn.net/a872822645/article/details/62217965
10.當(dāng)用戶在其他的Activity或者桌面回切到這個(gè)Activity時(shí),這個(gè)Activity就會(huì)先去執(zhí)行onRestart()函數(shù)缰泡,Restart有“重新開(kāi)始”的意思刀荒,然后接下來(lái)執(zhí)行onStart()函數(shù),接著執(zhí)行onResume()函數(shù)進(jìn)入到運(yùn)行狀態(tài)棘钞。
11.在“10”中講的很清楚了缠借。
12.高優(yōu)先級(jí)的應(yīng)用急需要內(nèi)存,此時(shí)處于低優(yōu)先級(jí)的此應(yīng)用就會(huì)被kill掉宜猜。
13.用戶返回原Activity泼返。
下面來(lái)著重說(shuō)明一下Activity每個(gè)生命周期函數(shù):
onCreate():
?表示Activity正在被創(chuàng)建,這是Activity生命周期的第一個(gè)方法姨拥。通常我們程序員要在此函數(shù)中做初始化的工作绅喉,比如:綁定布局,控件叫乌,初始化數(shù)據(jù)等柴罐。
onStart():
?表示Activity正在被啟動(dòng),這時(shí)候的Activity已經(jīng)被創(chuàng)建好了憨奸,完全過(guò)了準(zhǔn)備階段革屠,但是沒(méi)有出現(xiàn)在前臺(tái),需要執(zhí)行onResume()函數(shù)才可以進(jìn)入到前臺(tái)與用戶進(jìn)行交互排宰。
onResume():
?表示Activitiy已經(jīng)可見(jiàn)了似芝,并且Activity處于運(yùn)行狀態(tài),也就是Activity不止出現(xiàn)在了前臺(tái)额各,而且還可以讓用戶點(diǎn)擊国觉,滑動(dòng)等等操作與它進(jìn)行交互吧恃。
onPause():
?表示Activity正在暫停虾啦,大多數(shù)情況下,Activity執(zhí)行完onPause()函數(shù)后會(huì)繼續(xù)執(zhí)行onStop()函數(shù),造成這種函數(shù)調(diào)用的原因是當(dāng)前的Activity啟動(dòng)了另外一個(gè)Activity或者回切到上一個(gè)Activity傲醉。還有一種情況就是onPause()函數(shù)被單獨(dú)執(zhí)行了蝇闭,并沒(méi)有附帶執(zhí)行onStop()方法,造成這種函數(shù)調(diào)用的原因很簡(jiǎn)單硬毕,就是當(dāng)前Activity里啟動(dòng)了類(lèi)似于對(duì)話框的東東呻引。
onStop():
?表示Activity即將停止,我們程序員應(yīng)該在此函數(shù)中做一些不那么耗時(shí)的輕量級(jí)回收操作吐咳。
onRestart():
?表示Activity正在重新啟動(dòng)逻悠。一般情況下,一個(gè)存在于后臺(tái)不可見(jiàn)的Activity變?yōu)榭梢?jiàn)狀態(tài)韭脊,都會(huì)去執(zhí)行onRestart()函數(shù)童谒,然后會(huì)繼續(xù)執(zhí)行onStart()函數(shù),onResume()函數(shù)出現(xiàn)在前臺(tái)并且處于運(yùn)行狀態(tài)沪羔。
onDestory():
?表示Activity要被銷(xiāo)毀了饥伊。這是Activity生命中的最后一個(gè)階段,我們可以在onDestory()函數(shù)中做一些回收工作和資源釋放等蔫饰,比如:廣播接收器的注銷(xiāo)等琅豆。
1.2 異常情況下的Activity生命周期分析
??對(duì)于正常情況下的Activity生命周期,你應(yīng)該是比較清楚了篓吁,通常情況下茫因,Activity會(huì)碰到一些異常的情況,如果你沒(méi)對(duì)這些異常作合理的邏輯處理杖剪,某些情形下會(huì)讓用戶給你開(kāi)發(fā)的應(yīng)用給差評(píng)节腐。最嚴(yán)重的情況是用戶在使用應(yīng)用寫(xiě)了一篇字?jǐn)?shù)相當(dāng)之多的文章,某個(gè)操作突然讓當(dāng)前的Activity發(fā)生異常摘盆,如果你不把用戶辛苦半天寫(xiě)的文章數(shù)據(jù)保存下來(lái)翼雀,這個(gè)用戶肯定會(huì)罵爹的,而且會(huì)在應(yīng)用市場(chǎng)給你的應(yīng)用來(lái)波差評(píng)加吐槽孩擂,所以異常的邏輯處理是非常重要的狼渊,所以接下來(lái),我們來(lái)學(xué)習(xí)一下異常情況下的Activity生命周期类垦,學(xué)完后狈邑,你將會(huì)知道各種異常情況下如何作相應(yīng)的邏輯處理了。
情況1:資源相關(guān)的系統(tǒng)配置發(fā)生改變導(dǎo)致Activity被殺死并重新創(chuàng)建
??了解這個(gè)問(wèn)題之前蚤认,首先你得對(duì)Android資源加載機(jī)制有足夠的了解:
??Android資源加載機(jī)制鏈接:http://blog.csdn.net/thesingularityisnear/article/details/51581311
??在Activity系統(tǒng)配置發(fā)生改變之際米苹,如果你沒(méi)對(duì)Activity做任何處理,Activity就會(huì)被銷(xiāo)毀并且重新創(chuàng)建砰琢,這種情況下Activity會(huì)發(fā)生以下重建過(guò)程:
??,可以從圖中看出當(dāng)Activity發(fā)生意外的情況的時(shí)候蘸嘶,這里的意外指的就是系統(tǒng)配置發(fā)生改變良瞧,Activity會(huì)被銷(xiāo)毀,其onPause,OnStop,onDestory函數(shù)均會(huì)被調(diào)用训唱,同時(shí)由于Actiivty是在異常情況下終止的褥蚯,系統(tǒng)會(huì)調(diào)用onSaveInstanceState來(lái)保存當(dāng)前Activity狀態(tài)。調(diào)用onSaveInstanceState的時(shí)機(jī)總會(huì)發(fā)生在onStop之前况增,至于會(huì)不會(huì)調(diào)用時(shí)機(jī)發(fā)生在onPause方法之前赞庶,那就說(shuō)不定了,這個(gè)沒(méi)有固定的順序可言澳骤,正常情況下一般onSaveInstanceState不會(huì)被調(diào)用歧强。當(dāng)Activity被重新創(chuàng)建后,系統(tǒng)會(huì)調(diào)用onRestoreInstanceState,并且把Actiivty銷(xiāo)毀時(shí)onSaveInstanceState方法所保存的Bundle對(duì)象作為參數(shù)傳遞給onRestoreInstanceState和onCreate方法为肮。所以我們可以通過(guò)onRestoreInstanceState和onCreate方法來(lái)判斷Actiivty是否被重建了誊锭,如果被重建了,那么我們就可以取出之前保存的數(shù)據(jù)并恢復(fù)弥锄,從時(shí)序上來(lái)看丧靡,onRestoreInstanceState的調(diào)用時(shí)機(jī)發(fā)生在onStart之后。
??同時(shí)籽暇,在onSaveInstanceState和onRestoreInstanceState方法中温治,系統(tǒng)自動(dòng)為我們做了一定的恢復(fù)工作。當(dāng)Activity在異常情況下需要重新創(chuàng)建時(shí)戒悠,系統(tǒng)會(huì)默認(rèn)為我們保存當(dāng)前Activity的視圖結(jié)構(gòu)熬荆。當(dāng)Activity在異常情況下需要重新創(chuàng)建時(shí),系統(tǒng)會(huì)默認(rèn)為我們保存當(dāng)前Activity的視圖結(jié)構(gòu)绸狐,并且在Activity重啟后為我們恢復(fù)這些數(shù)據(jù)卤恳,比如:文本框中用戶輸入的數(shù)據(jù),ListView滾動(dòng)的位置等,這些View相關(guān)的狀態(tài)系統(tǒng)都能夠默認(rèn)為我們恢復(fù)寒矿。具體針對(duì)某一個(gè)特定的View系統(tǒng) 能為我們恢復(fù)哪些數(shù)據(jù)突琳,我們可以查看View的源碼。和Activity一樣符相,每個(gè)View都有onSaveInstanceState和onRestoreInstanceState這兩個(gè)方法拆融,看一下它們的具體實(shí)現(xiàn),就能知道系統(tǒng)能夠自動(dòng)為每個(gè)View恢復(fù)哪些數(shù)據(jù)啊终。
關(guān)于保存和恢復(fù)View層次結(jié)構(gòu)镜豹,系統(tǒng)的工作流程是這樣的:
??首先Activity被意外終止時(shí),Activity會(huì)調(diào)用onSaveInstanceState去保存數(shù)據(jù)蓝牲,然后Activity會(huì)委托Window去保存數(shù)據(jù)趟脂,接著Window在委托它上面的頂級(jí)容器去保存數(shù)據(jù)。頂級(jí)容器是一個(gè)ViewGroup例衍,一般來(lái)說(shuō)它很可能是DecorView昔期。最后頂層容器再去一一通知它的子元素來(lái)保存數(shù)據(jù)已卸,這樣整個(gè)數(shù)據(jù)保存過(guò)程就完成了≌蚓欤可以發(fā)現(xiàn)咬最,這是一個(gè)典型的委托思想翎嫡,上層委托下層欠动,父容器去委托子元素去處理一件事情,這種思想在Android中有很多應(yīng)用惑申,比如:View的繪制過(guò)程具伍,事件分發(fā)等都是采用類(lèi)似的思想。至于數(shù)據(jù)恢復(fù)過(guò)程也是類(lèi)似的圈驼,這樣就不再重復(fù)介紹了人芽。
情況2:資源內(nèi)存不足導(dǎo)致低優(yōu)先級(jí)的Activity被殺死
??首先,Activity有優(yōu)先級(jí)绩脆?你肯定懷疑萤厅,代碼中都沒(méi)設(shè)置過(guò)啊靴迫!優(yōu)先級(jí)從何而來(lái)惕味,其實(shí)這里的Activity的優(yōu)先級(jí)是指一個(gè)Activity對(duì)于用戶的重要程度,比如:正在與用戶進(jìn)行交互的Activity那肯定是最重要的玉锌。我們可以按照重要程度將Activity分為以下等級(jí):
優(yōu)先級(jí)最高: 與用戶正在進(jìn)行交互的Activity名挥,即前臺(tái)Activity。
優(yōu)先級(jí)中等:可見(jiàn)但非前臺(tái)的Activity,比如:一個(gè)彈出對(duì)話框的Activity,可見(jiàn)但是非前臺(tái)運(yùn)行主守。
優(yōu)先級(jí)最低:完全存在與后臺(tái)的Activity,比如:執(zhí)行了onStop禀倔。
??當(dāng)內(nèi)存嚴(yán)重不足時(shí),系統(tǒng)就會(huì)按照上述優(yōu)先級(jí)去kill掉目前Activity所在的進(jìn)程参淫,并在后續(xù)通過(guò)onSaveInstanceState和onRestoreInstanceState來(lái)存儲(chǔ)和恢復(fù)數(shù)據(jù)救湖。如果一個(gè)進(jìn)程中沒(méi)有四大組件的執(zhí)行,那么這個(gè)進(jìn)程將很快被系統(tǒng)殺死涎才,因此捎谨,一些后臺(tái)工作不適合脫離四大組件獨(dú)立運(yùn)行在后臺(tái)中,這樣進(jìn)程更容易被殺死憔维。比較好的方法就是將后臺(tái)工作放入Service中從而保證進(jìn)程有一定的優(yōu)先級(jí)涛救,這樣就不會(huì)輕易地被系統(tǒng)殺死。
-
總結(jié):
上面分析了系統(tǒng)的數(shù)據(jù)存儲(chǔ)和恢復(fù)機(jī)制业扒,我們知道检吆,當(dāng)系統(tǒng)配置發(fā)生改變之后,Activity會(huì)被重新創(chuàng)建程储,那么有沒(méi)有辦法不重新創(chuàng)建呢蹭沛?答案是有的臂寝,接下來(lái)我們就來(lái)分析這個(gè)問(wèn)題。系統(tǒng)配置中有很多內(nèi)容摊灭,如果某項(xiàng)內(nèi)容發(fā)生了該變后咆贬,我們不想系統(tǒng)重新創(chuàng)建Activity可以給Activity指定configChanges屬性。比如我們不想讓Actiivty在屏幕旋轉(zhuǎn)的時(shí)候重新創(chuàng)建帚呼,就可以給configChanges屬性添加orientation這個(gè)值掏缎,如下所示。android:configChanges = "orientation"
??如果我們指定多個(gè)值煤杀,那么就用“|”連接起來(lái)即可眷蜈,下表是configChanges的屬性含義表:
2.Activity的啟動(dòng)模式全面分析
??Activity的啟動(dòng)模式,你在初學(xué)期間一定很熟悉了吧沈自!不管你是否熟悉還是不熟悉酌儒,跟隨筆者的思路把Activity的啟動(dòng)模式整理一遍:
問(wèn)題1:Activity為什么需要啟動(dòng)模式?
問(wèn)題2:Activity的啟動(dòng)模式有哪些枯途?特性如何
問(wèn)題3:如何給Activity選擇合適的啟動(dòng)模式
問(wèn)題1:Activity為什么需要啟動(dòng)模式忌怎?
??我們都知道啟動(dòng)一個(gè)Activity后,這個(gè)Activity實(shí)例就會(huì)被放入任務(wù)棧中酪夷,當(dāng)點(diǎn)擊返回鍵的時(shí)候榴啸,位于任務(wù)棧頂層的Activity就會(huì)被清理出去,當(dāng)任務(wù)棧中不存在任何Activity實(shí)例后捶索,系統(tǒng)就回去回收這個(gè)任務(wù)棧插掂,也就是程序退出了。這只是對(duì)任務(wù)棧的基本認(rèn)識(shí)腥例,深入學(xué)習(xí)辅甥,筆者會(huì)在之后文章中提到。那么問(wèn)題來(lái)了燎竖,既然每次啟動(dòng)一個(gè)Activity就會(huì)把對(duì)應(yīng)的要啟動(dòng)的Activity的實(shí)例放入任務(wù)棧中璃弄,假如這個(gè)Activity會(huì)被頻繁啟動(dòng),那豈不是會(huì)生成很多這個(gè)Activity的實(shí)例嗎构回?對(duì)內(nèi)存而言這可不是什么好事夏块,明明可以一個(gè)Activity實(shí)例就可以應(yīng)付所有的啟動(dòng)需求,為什么要頻繁生成新的Activity實(shí)例呢纤掸?杜絕這種內(nèi)存的浪費(fèi)行為脐供,所以Activity的啟動(dòng)模式就被創(chuàng)造出來(lái)去解決上面所描述的問(wèn)題。
問(wèn)題2:Activity的啟動(dòng)模式有哪些借跪?特性如何
??Activity的啟動(dòng)模式有4種政己,分別是:standard,singleTop,singleTask和singleInstance。下面一一作介紹:
1.系統(tǒng)默認(rèn)的啟動(dòng)模式:standard
??標(biāo)準(zhǔn)模式掏愁,這也是系統(tǒng)的默認(rèn)模式歇由。每次啟動(dòng)一個(gè)Activity都會(huì)重新創(chuàng)建一個(gè)新的實(shí)例卵牍,不管這個(gè)實(shí)例是否存在。被創(chuàng)建的實(shí)例的生命周期符合典型情況下的Activity的生命周期沦泌。在這種模式下糊昙,誰(shuí)啟動(dòng)了這個(gè)Activity,那么這個(gè)Activity就運(yùn)行在啟動(dòng)它的那個(gè)Activity的任務(wù)棧中。比如Activity A啟動(dòng)了Activity B(B是標(biāo)準(zhǔn)模式)谢谦,那么B就會(huì)進(jìn)入到A所在的任務(wù)棧中释牺。有個(gè)注意的地方就是當(dāng)我們用ApplicationContext 去啟動(dòng)standard模式的Activity就會(huì)報(bào)錯(cuò),這是因?yàn)閟tandard模式的Actiivty默認(rèn)會(huì)進(jìn)入啟動(dòng)它的Activity所屬的任務(wù)棧中他宛,但是由于非Activity類(lèi)型的Context(如ApplicationContext)并沒(méi)有所謂的任務(wù)棧船侧,所以這就會(huì)出現(xiàn)錯(cuò)誤欠气。解決這個(gè)問(wèn)題的方法就是為待啟動(dòng)的Activity指定FLAG_ACTIVITY_NEW_TASK標(biāo)記位厅各,這樣啟動(dòng)的時(shí)候就會(huì)為它創(chuàng)建一個(gè)新的任務(wù)棧,這個(gè)時(shí)候啟動(dòng)Activity實(shí)際上以singleTask模式啟動(dòng)的预柒,讀者可以自己仔細(xì)體會(huì)队塘。
2.棧頂復(fù)用模式:singleTop
??在這種模式下,如果新的Activity已經(jīng)位于任務(wù)棧的棧頂宜鸯,那么此Activity不會(huì)被重新創(chuàng)建憔古,同時(shí)它的onNewIntent方法被回調(diào),通過(guò)此方法的參數(shù)我們可以取出當(dāng)前請(qǐng)求的信息淋袖。需要注意的是鸿市,這個(gè)Activity的onCreate,onStart不會(huì)被系統(tǒng)調(diào)用,因?yàn)樗](méi)有發(fā)生改變即碗。如果新的Activity已經(jīng)存在但不是位于棧頂焰情,那么新的Activity仍然會(huì)重新重建。舉個(gè)例子剥懒,假設(shè)目前棧內(nèi)的情況為ABCD,其中ABCD為四個(gè)Activity,A位于棧低内舟,D位于棧頂,這個(gè)時(shí)候假設(shè)要再次啟動(dòng)D,如果D的啟動(dòng)模式為singleTop,那么棧內(nèi)的情況依然為ABCD;如果D的啟動(dòng)模式為standard,那么由于D被重新創(chuàng)建初橘,導(dǎo)致棧內(nèi)的情況為ABCDD验游。
3.棧內(nèi)復(fù)用模式:singleTask
??這是一種單例實(shí)例模式,在這種模式下保檐,只要Activity在一個(gè)棧中存在耕蝉,那么多次啟動(dòng)此Activity都不會(huì)重新創(chuàng)建實(shí)例,和singleTop一樣夜只,系統(tǒng)也會(huì)回調(diào)其onNewIntent垒在。具體一點(diǎn),當(dāng)一個(gè)具有singleTask模式的Activity請(qǐng)求啟動(dòng)后盐肃,比如Activity A爪膊,系統(tǒng)首先尋找任務(wù)棧中是否已存在Activity A的實(shí)例权悟,如果已經(jīng)存在,那么系統(tǒng)就會(huì)把A調(diào)到棧頂并調(diào)用它的onNewIntent方法推盛,如果Activity A實(shí)例不存在峦阁,就創(chuàng)建A的實(shí)例并把A壓入棧中。舉幾個(gè)栗子:
- 比如目前任務(wù)棧S1的情況為ABC,這個(gè)時(shí)候Activity D以singleTask模式請(qǐng)求啟動(dòng)耘成,其所需的任務(wù)棧為S2榔昔,由于S2和D的實(shí)例均不存在,所以系統(tǒng)會(huì)先創(chuàng)建任務(wù)棧S2,然后再創(chuàng)建D的實(shí)例并將其投入到S2任務(wù)棧中瘪菌。
- 另外一種情況是撒会,假設(shè)D所需的任務(wù)棧為S1,其他情況如同上面的例子所示,那么由于S1已經(jīng)存在师妙,所以系統(tǒng)會(huì)直接創(chuàng)建D的實(shí)例并將其投入到S1诵肛。
- 如果D所需的任務(wù)棧為S1,并且當(dāng)前任務(wù)棧S1的情況為ADBC,根據(jù)棧內(nèi)復(fù)用的原則,此時(shí)D不會(huì)重新創(chuàng)建怔檩,系統(tǒng)會(huì)把D切換到棧頂并調(diào)用其onNewIntent方法薛训,同時(shí)由于singleTask默認(rèn)具有clearTop的效果锯岖,會(huì)導(dǎo)致棧內(nèi)所有在D上面的Activity全部出棧米酬,于是最終S1中的情況為AD。
??通過(guò)以上3個(gè)例子跳芳,你應(yīng)該能比較清晰地理解singleTask的含義了。
4.單實(shí)例模式:singleInstance
??這是一種加強(qiáng)的singleTask模式孽水,它除了具有singleTask模式所有的特性外测柠,還加強(qiáng)了一點(diǎn),那就是具有此種模式的Activity只能單獨(dú)位于一個(gè)任務(wù)棧中,換句話說(shuō)肠仪,比如Activity A是singleInstance模式意述,當(dāng)A啟動(dòng)后潮针,系統(tǒng)會(huì)為它創(chuàng)建一個(gè)新的任務(wù)棧每篷,然后A獨(dú)自在這個(gè)新的任務(wù)棧中,由于棧內(nèi)復(fù)用的特性仑嗅,后續(xù)的請(qǐng)求均不會(huì)創(chuàng)建新的Activity,除非這個(gè)獨(dú)特的任務(wù)棧被系統(tǒng)銷(xiāo)毀了。
- 總結(jié)
上面介紹了4種啟動(dòng)模式,這里需要指出一種情況,我們假設(shè)目前有2個(gè)任務(wù)棧未荒,前臺(tái)任務(wù)棧的情況為AB,而后臺(tái)任務(wù)棧的情況為CD寨腔,這里假設(shè)CD的啟動(dòng)模式均為singleTask∫惫玻現(xiàn)在請(qǐng)求啟動(dòng)D,那么整個(gè)后臺(tái)任務(wù)棧都會(huì)被切換到后臺(tái)上荡,這個(gè)時(shí)候整個(gè)后退列表變成了ABCD。當(dāng)用戶按back鍵的時(shí)候馒闷,列表中的Activity會(huì)一一出棧酪捡,如下圖1所示:
??如果不是請(qǐng)求的D而是請(qǐng)求的C,那么情況就不一樣了,如下圖2所示:
??如何指定活動(dòng)的啟動(dòng)模式呢窜司?在AndroidManifest.xml文件當(dāng)注冊(cè)活動(dòng)的代碼中去指定
比如:我要把MainActivity活動(dòng)的啟動(dòng)模式指定為singleInstance模式
Activity的Flags
??Activity的Flags有很多沛善,這里筆者就不羅嗦了,直接貼一個(gè)鏈接:
http://www.cnblogs.com/xgjblog/p/3994990.html
3.IntentFilter的匹配規(guī)則
??在初學(xué)期間塞祈,你已經(jīng)知道Activity的啟動(dòng)分為隱式和顯式金刁,那么什么是顯式啟動(dòng)一個(gè)Activitiy,什么又是隱式啟動(dòng)一個(gè)Activity呢?顯式啟動(dòng)一個(gè)Activity需要明確地指定被啟動(dòng)對(duì)象的組件信息尤蛮,包含包名和類(lèi)名媳友,顯式調(diào)用目的性太強(qiáng),滿足組件信息的只有那么一個(gè)Activity類(lèi)而已产捞,而隱式調(diào)用需要Intent能夠匹配目標(biāo)的IntentFilter中所設(shè)置的過(guò)濾信息醇锚,如果不匹配將無(wú)法啟動(dòng)目標(biāo)Activity。IntentFilter中的過(guò)濾信息有action,category,data坯临。原則上一個(gè)Intent是不應(yīng)該同時(shí)擁有隱式和顯式的Activity配置信息焊唬,但是如果同時(shí)都有的情況下啟動(dòng)的應(yīng)該是顯式的啟動(dòng)。下面是一個(gè)過(guò)濾規(guī)則的示例:
//此處來(lái)個(gè)截圖
??為了匹配過(guò)濾列表看靠,需要同時(shí)匹配過(guò)濾列表的action,category,data信息赶促,否則匹配失敗。一個(gè)過(guò)濾列表中的action,category,data可以有多個(gè)挟炬,所有的action,category,data分別構(gòu)成不同類(lèi)別鸥滨,同一類(lèi)別的信息共同約束當(dāng)前類(lèi)別的匹配過(guò)程。只有一個(gè)Intent同時(shí)匹配action類(lèi)別谤祖,category類(lèi)別,data類(lèi)別才算完全匹配婿滓,只有完全匹配才能成功啟動(dòng)目標(biāo)Activitry。另外一點(diǎn)粥喜,一個(gè)Activity可以有多個(gè)intent-filter規(guī)則凸主,組合你應(yīng)該知道哈,反是有多個(gè)action,category,data的都會(huì)有多個(gè)匹配規(guī)則容客,比如:假設(shè)一個(gè)Activity的action有3個(gè)秕铛,category有4個(gè),data有5個(gè)缩挑,那么這個(gè)Activity的匹配規(guī)則會(huì)有多少個(gè)呢?345個(gè)咯鬓梅,是不是很簡(jiǎn)單呢供置。下面我們就來(lái)分別詳細(xì)講講action,category,data的匹配規(guī)則。
3.1 action的匹配規(guī)則:
??action是一個(gè)字符串绽快,系統(tǒng)預(yù)定義一些action,同時(shí)我們也可以在應(yīng)用種定義自己的action芥丧。action的匹配規(guī)則是Intent中的action必須能夠和過(guò)濾規(guī)則中的action匹配,這里說(shuō)的是指action的字符串值完全一樣坊罢。一個(gè)過(guò)濾規(guī)則中可以有多個(gè)action,那么只要Intent中的action能夠和過(guò)濾規(guī)則中的任何一個(gè)action相同即可匹配成功续担。另外,action是區(qū)分大小寫(xiě)活孩,大小寫(xiě)不同字符串相同的action會(huì)匹配失敗物遇。
3.2 category的匹配規(guī)則:
??category是一個(gè)字符串,系統(tǒng)預(yù)定義了一些category,同時(shí)我們也可以在應(yīng)用中定義自己的category询兴。category的匹配規(guī)則和action不同乃沙,它要求Intent中如果含有category,那么所有的category都必須和過(guò)濾規(guī)則中的其中一個(gè)categroy相同。換句話說(shuō)诗舰,Intent中如果出現(xiàn)了category,不管有幾個(gè)category,對(duì)于每個(gè)category來(lái)說(shuō)警儒,它必須是過(guò)濾規(guī)則中已經(jīng)定義的category。當(dāng)然眶根,Intent可以沒(méi)有category,如果沒(méi)有category的話蜀铲,Intent仍然可以匹配成功的,說(shuō)到這里你可能會(huì)覺(jué)得這不科學(xué)啊属百,其實(shí)這個(gè)匹配規(guī)則理解起來(lái)很簡(jiǎn)單蝙茶,就是高中的集合思想,就是判斷Intent中的category構(gòu)成的集合是否為啟動(dòng)Activity的category過(guò)濾規(guī)則構(gòu)成集合的子集诸老,這很簡(jiǎn)單吧隆夯!但是注意與action的匹配規(guī)則相區(qū)別,action是要求Intent必須有一個(gè)action且必須能夠和過(guò)濾規(guī)則中的某個(gè)action相同别伏,這不就是交集的意思嗎?瞬間你就會(huì)懂得了action的匹配規(guī)則其實(shí)就是集合的交集思想蹄衷,而category的匹配規(guī)則其實(shí)就是集合的子集思想±灏梗總結(jié)來(lái)說(shuō):對(duì)于action的匹配規(guī)則是這樣的愧口,Intent中的action所構(gòu)成的集合和Activity過(guò)濾規(guī)則中action構(gòu)成的集合有交集的話才能匹配上,而對(duì)于category的匹配規(guī)則是這樣的类茂,Intent中的category所構(gòu)成的集合是Activity過(guò)濾規(guī)則中category構(gòu)成的集合的子集能匹配上耍属。其實(shí)很簡(jiǎn)單action-->交集,categroy-->子集巩检。
3.3 data的匹配規(guī)則:
??data的匹配規(guī)則和action相似厚骗,如果過(guò)濾規(guī)則中定義了data,那么Intent中必須也要定義可匹配的data。在介紹data的匹配規(guī)則之前兢哭,我們需要先了解一下data的結(jié)構(gòu):
data的結(jié)構(gòu):
??data的語(yǔ)法如下所示:
<data android:scheme="string"
android:host="string"
android:port="string"
android:path="string"
android:pathPattern="string"
android:pathprefix="string"
android:mimeType="string"/>
??data由兩部分組成领舰,mimeType和URI。mimeType指媒體類(lèi)型迟螺,比如:image/jpeg,audio/mpeg4-generic和vedio/*等冲秽,可以表示圖片,文本矩父,視頻等不同的媒體格式锉桑,而URI中包含的數(shù)據(jù)就比較多了,下面是URI的結(jié)構(gòu):
<scheme>://<host>:<port>/<path>|<pathprefix>|<pathPattern>