App進(jìn)程被殺所引發(fā)的問(wèn)題及其處理方案

開始先假設(shè)有這樣一個(gè)簡(jiǎn)單的情景:當(dāng)前應(yīng)用中有3個(gè)Activity AAcitity BActivity CActivity在當(dāng)前的Activity棧中處于棧頂?shù)臑镃。接著按下home鍵此時(shí)3個(gè)activity都處于"stoped"狀態(tài)。但這種情景下應(yīng)有有可能會(huì)被殺掉。

stack.png

一 被殺的原因

在官方文檔中關(guān)于Activity生命周期的部分可以看到這樣的描述:

If an activity is paused or stopped, the system can drop the activity from memory by either asking it to finish, or simply killing its process. When it is displayed again to the user, it must be completely restarted and restored to its previous state.

大概的意思是當(dāng)內(nèi)存不足的時(shí)候應(yīng)用是可能被"殺"掉的。通過(guò)下面文檔的表格可以看出,當(dāng)activity處于stoped、destroyed以及paused(3.0版本以前)的狀態(tài)時(shí)所在進(jìn)程都有可能被殺掉(當(dāng)然這里的activity的狀態(tài)是對(duì)應(yīng)activity棧頂?shù)臓顟B(tài))。

killabel.png

二 被殺后所產(chǎn)生的現(xiàn)象

  • 可能有人會(huì)有這樣的疑問(wèn):當(dāng)應(yīng)用被強(qiáng)殺掉,所有在當(dāng)前Activity棧中的Activity(此時(shí)處于stopped狀態(tài))進(jìn)程被殺掉的時(shí)候會(huì)像調(diào)用finish那樣結(jié)束掉自己?jiǎn)?通過(guò)測(cè)試可以得出答案:不會(huì)(你可以通過(guò)ddms模擬系統(tǒng)殺掉你的進(jìn)程進(jìn)行測(cè)試就可以得出這樣的結(jié)論)。在開頭描述的情景下殺掉進(jìn)程的話,所有Activity都不會(huì)走onStop和onDestroy方法。所以這種情況下關(guān)閉數(shù)據(jù)庫(kù)、文件之類的操作最好考慮放到onPause中進(jìn)行了。

  • 如果你有在onSaveInstanceState(Bundle)做數(shù)據(jù)保存的話,這時(shí)候就應(yīng)該要注意了,通過(guò)測(cè)試你會(huì)知道應(yīng)用被強(qiáng)殺后activity不會(huì)調(diào)用到onSaveInstanceState(Bundle)(或許這時(shí)候你可以考慮提前在onPause()中作相應(yīng)的處理)。

  • 當(dāng)應(yīng)有被殺掉后,你再重新打開應(yīng)用的話是打開最近可見的activity對(duì)應(yīng)于情景的CActivity,這時(shí)候如果你再返回按鈕會(huì)發(fā)現(xiàn)會(huì)回到BActivity,當(dāng)然再按一次就回到AActivity??梢夾ctivity棧并沒有因?yàn)閼?yīng)用被殺掉而清空。但這里有一點(diǎn)要注意的是,這種情況下棧中Activity重新實(shí)例化,因?yàn)橹皸V械腁ctivity其實(shí)已經(jīng)被銷毀了。這一點(diǎn)可以通過(guò)打印應(yīng)用被殺前后的Activity對(duì)象的hash值得到驗(yàn)證。

Paste_Image.png

三 被殺后重新打開可能發(fā)生的問(wèn)題

根據(jù)二中提到的現(xiàn)象因?yàn)閼?yīng)用被強(qiáng)殺而數(shù)據(jù)得不到恢復(fù)的話可能就會(huì)出現(xiàn)問(wèn)題,例如BActivity啟動(dòng)通過(guò)bundle攜帶數(shù)據(jù)到CActivity中,但當(dāng)重新打開應(yīng)用時(shí)數(shù)據(jù)因?yàn)锽Activity還沒有實(shí)例化,CActivty中就獲取不到正確的數(shù)據(jù)了。另外一種可能出現(xiàn)的問(wèn)題是假設(shè)CActivty中使用了BActivity中的靜態(tài)引用reference,而該引用是隨BActivity的實(shí)例化而實(shí)例化的,所以CActivity中使用的只是一個(gè)指向空的引用這樣使用就會(huì)報(bào)空指針了。當(dāng)然實(shí)際開發(fā)中在各種情形下因?yàn)閺?qiáng)殺后再啟動(dòng)應(yīng)用也會(huì)引起其他問(wèn)題。

四 被殺后的處理

當(dāng)然最好的處理方法是讓數(shù)據(jù)重新的恢復(fù)并且避免三中提及到的以及可能出現(xiàn)的各種問(wèn)題。但這就要根據(jù)具體的項(xiàng)目去做處理了。這里主要介紹另一種方案就是 當(dāng)重啟應(yīng)用時(shí)清空Activity棧并且重新從AActvity開始launcher應(yīng)用。這樣就繞開了數(shù)據(jù)恢復(fù)的問(wèn)題。但這里注意的一點(diǎn)是假設(shè)你在CActivity中根據(jù)你所設(shè)置的標(biāo)志判斷到應(yīng)用需要重走流程starActivity的時(shí)候,需要將intent的flags設(shè)置為

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);

這樣做才能把先前的棧清空。

參考文章: http://www.itdecent.cn/p/bce1164b83d8

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容