今日 有喜有悲!
寫這個(gè)文章的時(shí)候 skt 已經(jīng)被msf 打成2:1了 嗯 很開森....
然而悲劇是 今天2個(gè)安卓同事一休假,MMP 生產(chǎn)就出問題了報(bào)了個(gè)OOM ,嚇?biāo)览献恿肆笪R詾橐穾Я耍?br>
于是我就分析了下今天這個(gè)事情的由來
通過本文的閱讀 我將授予你
1 首先來看
操作步驟
點(diǎn)擊購物車 點(diǎn)擊結(jié)算 然后崩潰掉了
機(jī)型是小米note 內(nèi)存為3g
當(dāng)時(shí)我就覺得不應(yīng)該啊 因?yàn)楫吘?個(gè)g 的內(nèi)存
![Uploading image_401928.png . . .]
接著開始解析開始
---------分析原因 :
1 在內(nèi)存不足的情況下 創(chuàng)建訂單頁面失敗了 然后系統(tǒng)產(chǎn)生gc
2 在由購物車頁面?zhèn)鬟f參數(shù)的情況下 傳遞了參數(shù)給訂單頁面 然后發(fā)送了gc導(dǎo)致訂單頁面創(chuàng)建失敗 所以導(dǎo)致訂單頁面創(chuàng)建失敗導(dǎo)致崩潰(為了驗(yàn)證這個(gè)問題 在傳遞過來的參數(shù)我們做了非空校驗(yàn) 然后我現(xiàn)在 在傳遞成功的情況下 然后將其參數(shù)清理掉 然后 看創(chuàng)建是否會(huì)成功 如果成功 證明不是這個(gè)問題 )驗(yàn)證結(jié)果是我不傳入?yún)?shù)也會(huì)創(chuàng)建成功 只是沒有商品而已 所以就不是這個(gè)原因
所以說 傳遞數(shù)據(jù)為空 即使被回收也不會(huì)影響使用 也不會(huì)崩潰 導(dǎo)致oom 的原因
3 在log 日子 發(fā)現(xiàn) onResume 方法 發(fā)覺是在onResume中 事實(shí)上 在onResume 和onPause 中我都沒寫任何東西 炭菌。就是說是在執(zhí)行 onResume 方法的時(shí)候才崩潰的 也就是之前已經(jīng)創(chuàng)建過一次了 然后 在此進(jìn)入
思考: 根據(jù)onResume 方法的場景 一共3種
1 一個(gè)Activity啟動(dòng)另一個(gè)Activity: onPause()->onStop(),再返回:onRestart()->onStart()->onResume()
2 程序按back 退出: onPause()->onStop()->onDestory(),再進(jìn)入:onCreate()->onStart()->onResume();
3 程序按home 退出: onPause()->onStop(),再進(jìn)入:onRestart()->onStart()->onResume();
--------細(xì)節(jié)方面的處理 Activity 第一次創(chuàng)建時(shí)會(huì)調(diào)用 onCreate(Bundle)。 該方法用于創(chuàng)建 Activity 的用戶界面痢畜,創(chuàng)建所需的后臺(tái)線程,并執(zhí)行其他的全局初始化。如果能獲得Activity以前的狀態(tài)丁稀,就可以將包含此狀態(tài)的 android.os.Bundle 對象傳給onCreate()吼拥;否則就傳入一個(gè)空引用。在調(diào)用 onCreate(Bundle)之后线衫。
Android 總是會(huì)調(diào)用onStop()的;
so! 真相只有一個(gè)凿可!
那就是還得繼續(xù)分析。授账。枯跑。。白热。敛助。
--------- 所以在activity 不操作的時(shí)候 不外乎2中 退出 不顯示 和意外退出的時(shí)候 保存下Bundle 在下次進(jìn)來的時(shí)候判斷是否為空 如果不為空就加載上次的在onstop 方法中調(diào)用保存就行了因?yàn)槭冀K會(huì)調(diào)用onstop 方法。但是 還有一種究極情況.
----------內(nèi)存不夠 android 會(huì)托管acvitity 這個(gè)時(shí)候屋确。
----------在 Activity 被銷毀之前會(huì)調(diào)用 onDestroy()纳击,除非是內(nèi)存不夠, Android 強(qiáng)行終止了Activity 的進(jìn)程攻臀。在這種情況下就不會(huì)調(diào)用 onDestroy()焕数。如果調(diào)用了 onDestroy(),那它就是該 Activity 接收的最終調(diào)用刨啸。在 onPause()堡赔、 onStop()或 onDestroy()返回之后, Android 可以終止托管 Activity 的進(jìn)程呜投。從 onPause()返回后到調(diào)用 onResume()之前加匈, Activity 都處于可終止?fàn)顟B(tài)。在 onPause()再次返回之前仑荐, Activity 都不會(huì)再處于可終止?fàn)顟B(tài).
---------上面的話看起來有點(diǎn)繞雕拼。但是其實(shí)如果你用心了解過安卓的內(nèi)核機(jī)制就會(huì)明白.所有的安卓進(jìn)程都是用zygote這個(gè)進(jìn)程frok 出來的。所以我們在崩潰日志可以很容易看到這個(gè)詞粘招。你必須要了解到activity 的原理啥寇。我們的activity 都是由activityThead 管理的 所以在托管的時(shí)候都是由系統(tǒng)幫我們管理的。
接下來 我們看看什么情況才會(huì)android才會(huì)觸發(fā)gc 機(jī)制洒扎。(http://blog.csdn.net/cscs111/article/details/77558168) 可以看這個(gè)文章
自己去閱讀這個(gè)android的gc 機(jī)制 我這邊直接說結(jié)果了
--------activity 如果要被回收掉 虛擬機(jī)要使用的內(nèi)存必須要超過最大內(nèi)存的3/4 這個(gè)時(shí)候才會(huì)觸發(fā)一次 大規(guī)模的Gc 回收掉activity 這個(gè)時(shí)候不管app 是在運(yùn)行或者是低內(nèi)存的運(yùn)行狀態(tài)下都是如此 剩下的情況就只有activity 在onstop 之后才會(huì)觸發(fā) 所以在activity 在執(zhí)行了onstop 之后沒有被finish 或者x銷毀的時(shí)候 才會(huì)進(jìn)行回收 之后才會(huì)在Activity 的performDestroy 中執(zhí)行 ondestroy 然后就等待GC回收的處理了辑甜。
所以
于是 .........問題的定位就是 在執(zhí)行onResume 方法的時(shí)候 發(fā)生了gc 無解。只能在之前的時(shí)候 界面不可見得時(shí)候 我們保存在Bundle 中 然后 activity由于系統(tǒng)內(nèi)存不足時(shí)被殺死袍冷,在onSaveInstanceState方法里存儲(chǔ)數(shù)據(jù)磷醋,onCreate時(shí)取出數(shù)據(jù)。 onSaveInstanceState 的調(diào)用是由于android 的framework幫忙調(diào)用的 ? onSaveInstanceState方法是Activity的生命周期方法胡诗,主要用于在Activity銷毀時(shí)保存一些信息邓线。當(dāng)Activity只執(zhí)行onPause方法時(shí)(Activity a打開一個(gè)透明Activity b)這時(shí)候如果App設(shè)置的targetVersion大于android3.0則不會(huì)執(zhí)行onSaveInstanceState方法淌友。當(dāng)Activity執(zhí)行onStop方法時(shí),通過分析源碼我們知道調(diào)用onSaveInstanceState的方法直接傳值為true骇陈,所以都會(huì)執(zhí)行onSaveInstanceState方法震庭。
所以------ 能夠解決大部分問題 因?yàn)閍ctivity 創(chuàng)建的時(shí)間很短 所以 很快就會(huì)執(zhí)行了到onResume 如果不執(zhí)行onstop 就無法保存了。
哎........其實(shí)谷歌的思想是沒有錯(cuò)誤的, 因?yàn)槟阋粋€(gè)app 都占了3/4的內(nèi)存了, 肯定要回收的啊 主要是 android 其他的app 占了內(nèi)存 如果你占了3/4 都還不夠用 只能說你的app 差你雌。問題是 app 根本沒有占到3/4嘛 器联!mmp