既然是探究Activity異常情況下的生命周期叹坦,首先就得搞明白Activity在哪些情況下會(huì)出現(xiàn)異常情況。在實(shí)際的開(kāi)發(fā)過(guò)程中卑雁,我們經(jīng)常會(huì)碰到的異常情況大概有以下兩種募书。
情況一:資源相關(guān)的系統(tǒng)配置發(fā)生改變導(dǎo)致Activity被殺死并重新創(chuàng)建绪囱。
這種情況產(chǎn)生的可能性會(huì)很多,最常見(jiàn)的就是旋轉(zhuǎn)屏幕莹捡,當(dāng)然還有就是系統(tǒng)提供的模式切換等等鬼吵。當(dāng)然,針對(duì)異常情況篮赢,系統(tǒng)本身提供了方法供我們處理后續(xù)事件齿椅。最重要的兩個(gè)方法就是onSaveInstanceState和onRestoreInstanceState,其中onSaveInstanceState用于在異常情況下Activity被銷(xiāo)毀時(shí)保存我們想要保存的數(shù)據(jù)启泣,onRestoreInstanceState用于異常情況下的Activity被銷(xiāo)毀重建后獲取保存的數(shù)據(jù)涣脚。下面我們以旋轉(zhuǎn)屏幕來(lái)舉例。
首先我們來(lái)看一下異常情況下Activity的生命周期執(zhí)行情況:
注意看寥茫,當(dāng)我們旋轉(zhuǎn)手機(jī)屏幕的時(shí)候遣蚀,首先執(zhí)行了onPause方法,緊接著執(zhí)行onSaveInstanceState方法纱耻,在這里我們可以對(duì)我們需要保存的數(shù)據(jù)進(jìn)行處理了芭梯,最后執(zhí)行onStop->onDestroy,到這里意味著MainActivity被銷(xiāo)毀了弄喘。但是緊接著你會(huì)發(fā)現(xiàn)MainActivity會(huì)被重新創(chuàng)建玖喘,它會(huì)執(zhí)行onCreate->onStart->onRestoreInstanceState->onResume方法,我們可以很清楚的看到限次,創(chuàng)建MainActivity所執(zhí)行的方法里面比正常情況下的生命周期多了一個(gè)
onRestoreInstanceState方法芒涡,那么現(xiàn)在我們來(lái)試一試如果在onSaveInstanceState保存數(shù)據(jù),在onRestoreInstanceState方法里面是否能夠拿到我們保存的數(shù)據(jù)卖漫,對(duì)MainActivity做稍微修改,如下:
這個(gè)代碼很簡(jiǎn)單赠群,就是在onSaveInstanceState里面存一個(gè)key為name羊始,值為stevens的數(shù)據(jù),
然后在onRestoreInstanceState里面拿出這個(gè)數(shù)據(jù)查描,注意需要進(jìn)行非空判斷突委,現(xiàn)在運(yùn)行程序看看打印的結(jié)果。
發(fā)現(xiàn)沒(méi)有冬三,發(fā)現(xiàn)沒(méi)有匀油,我們真的在onRestoreInstanceState方法里面拿到了我們之前存儲(chǔ)的數(shù)據(jù)啦。
情況二:資源內(nèi)存不足導(dǎo)致優(yōu)先級(jí)低的Activity被系統(tǒng)殺死勾笆。
做過(guò)Android開(kāi)發(fā)的童靴都知道敌蚜,手機(jī)本身是有內(nèi)存限制的,就是我們經(jīng)常用來(lái)描述手機(jī)的4G窝爪、8G內(nèi)存弛车,其實(shí)手機(jī)的內(nèi)存是指的整個(gè)手機(jī)齐媒,而每個(gè)手機(jī)上面都會(huì)安裝很多的APP,所以手機(jī)系統(tǒng)分配給每個(gè)APP的內(nèi)存都是有限的纷跛,而當(dāng)一個(gè)APP開(kāi)啟了很多Activity的時(shí)候喻括,其實(shí)每個(gè)Activity都是有各種不同狀態(tài)的,其狀態(tài)對(duì)應(yīng)的就是運(yùn)行的優(yōu)先級(jí)贫奠,具體來(lái)說(shuō)唬血,Activity的優(yōu)先級(jí)按照從高到低可以分為三種:
(1)前臺(tái)Activity —— 當(dāng)前顯示的Activity,正在和用戶(hù)交互的Activity唤崭,其優(yōu)先級(jí)最高刁品。
(2)可見(jiàn)但是非前臺(tái)Activity —— 怎么理解可見(jiàn)但是非前臺(tái),舉一個(gè)例子你就明白了浩姥,比如我在當(dāng)前的Activity彈出了一個(gè)Dialog挑随,那么此時(shí)的Activity就處于可見(jiàn)但非前臺(tái),其優(yōu)先級(jí)略低勒叠。
(3)后臺(tái)Activity —— 不可見(jiàn)Activity兜挨,比如我從A跳到B,當(dāng)B顯示后眯分,A就處于后臺(tái)狀態(tài)拌汇,其優(yōu)先級(jí)最低。
當(dāng)系統(tǒng)內(nèi)存不足的時(shí)候弊决,系統(tǒng)會(huì)按照優(yōu)先級(jí)的高低來(lái)選擇殺死哪些Activity噪舀,這種情況不太好模擬,但是其執(zhí)行的生命周期和情況一一樣飘诗,包括執(zhí)行的onSaveInstanceState和onRestoreInstanceState方法与倡,這里就不作過(guò)多講解了。
上面分析了系統(tǒng)的數(shù)據(jù)的存儲(chǔ)和恢復(fù)機(jī)制昆稿,我們知道當(dāng)系統(tǒng)資源發(fā)生改變時(shí)Activity就會(huì)被銷(xiāo)毀重建纺座,那么有沒(méi)有什么辦法可以避免Activity銷(xiāo)毀重建呢?答案肯定是可以的溉潭,因?yàn)橄到y(tǒng)為我們提供了configChanges屬性净响,用它可以指定在哪些情況下不重建當(dāng)前的activity。
configChanges的取值很多喳瓣,我們列舉幾個(gè)常用的就可以了馋贤。
<1> configChanges = “orientation”
屏幕方向發(fā)生了改變
<2> configChanges = “l(fā)ocale”
設(shè)備的位置發(fā)生了改變,一般指切換了語(yǔ)言
<3> configChanges = “keyboardHidden”
鍵盤(pán)的可訪(fǎng)問(wèn)性發(fā)生了改變畏陕,比如用戶(hù)調(diào)出了鍵盤(pán)
當(dāng)然配乓,configChanges可供選擇的值遠(yuǎn)遠(yuǎn)不只這些,具體可以自行去百度。那么現(xiàn)在我們就來(lái)試試當(dāng)我們?cè)O(shè)置configChanges = “orientation”時(shí)扰付,旋轉(zhuǎn)手機(jī)屏幕會(huì)發(fā)生什么堤撵。
首先在我們的清單文件當(dāng)中加上這么一句:
運(yùn)行一下程序看下打印的文件
我們會(huì)發(fā)現(xiàn)當(dāng)旋轉(zhuǎn)手機(jī)屏幕之后,MainActivity沒(méi)有做任何動(dòng)作羽莺,MainActivity沒(méi)有被銷(xiāo)毀重建实昨,onSaveInstanceState和onRestoreInstanceState方法也沒(méi)有被調(diào)用。取而代之的是onConfigurationChanged方法被調(diào)用盐固,我們可以在這里做我們想要的操作了荒给。
關(guān)于Activity異常情況下的生命周期就分享到這里了,歡迎大家在下面留言評(píng)論刁卜。