LeakCanary內(nèi)存泄漏檢測(cè)原理:
(1).application中注冊(cè)Activity生命周期onActivityDestory回調(diào),同樣的檢測(cè)fragment也是通過監(jiān)聽Fragment的生命周期,利用fragmentManager.registerFragmentLifecycleCallbacks可以實(shí)現(xiàn)Fragment是在onFragmentDestroy()中檢測(cè)Fragment對(duì)象是否泄露。
(2).在回調(diào)方法中創(chuàng)建引用隊(duì)列關(guān)聯(lián)activity弱引用對(duì)象KeyedWeakReference實(shí)例,并將KeyedWeakReference對(duì)象存放在集合中保存
KeyedWeakReference reference = new KeyedWeakReference(activity,referenceQueue);KeyedWeakReference繼承自WeakReference
(3).首先遍歷集合判斷弱引用隊(duì)列中是否包含activity,如果包含說明對(duì)象被回收將其從集合中刪除,不包含說明可能存在內(nèi)存泄漏需要進(jìn)一步檢查
(4).在主線程空閑的時(shí)候(Looper.getMainLooper().addIdle())再次檢查引用隊(duì)列中是否包含activity,如果依然不包含,調(diào)用System.gc()進(jìn)行g(shù)c回收,因?yàn)間c操作不是同步操作,所以sleep(100)ms后再次檢查是否發(fā)生內(nèi)存泄漏
(5).發(fā)生了內(nèi)存泄漏:Debug.dumpHprofData(String fileName)文件分析內(nèi)存泄漏對(duì)象到GC root的引用鏈并發(fā)送泄漏信息給RD.
LMK殺死進(jìn)程優(yōu)先級(jí)
1.前臺(tái)進(jìn)程:與用戶正在交互的進(jìn)程
2.可見進(jìn)程:用戶可見但不可交互,比如Activity上彈出對(duì)話框這種情境下,Activity雖然可見但失去了焦點(diǎn)
3.服務(wù)進(jìn)程:app處于后臺(tái),使用service在播放音樂或者下載文件這種情景下
4.后臺(tái)進(jìn)程:app處于后臺(tái),頁面組件不可見,比如執(zhí)行了Actity的onStop
5.空進(jìn)程:app處于后臺(tái)但是沒有活動(dòng)的組件在運(yùn)行,空進(jìn)程存在的目的在于能夠快速響應(yīng)用戶點(diǎn)擊圖標(biāo)喚醒進(jìn)程。
當(dāng)兩個(gè)應(yīng)用的進(jìn)程優(yōu)先級(jí)相同時(shí),LMK優(yōu)先殺死占有內(nèi)存高的進(jìn)程。
監(jiān)聽進(jìn)程內(nèi)存狀態(tài)
兩種實(shí)現(xiàn)方式
(1).Application和Activity中的onTrimMemory(int level)系統(tǒng)回調(diào),level等級(jí)有應(yīng)用處于前臺(tái),系統(tǒng)內(nèi)存不足,該進(jìn)程馬上要被kill掉等
(2).調(diào)用activityManager.getMemoryInfo()查詢內(nèi)存信息,包括應(yīng)用剩下可用內(nèi)存,應(yīng)用總內(nèi)存以及布爾值的系統(tǒng)是否處于低內(nèi)存狀態(tài)等信息。
LocalBordcastManager線程安全的單例實(shí)現(xiàn)類,通過handler發(fā)送消息切換到主線程來執(zhí)行,適合進(jìn)程內(nèi)通信
Class ReceiverRecord{
BroadcastReceiver receiver;
IntentFilter filter;
boolean broadcasting;
}
class BroadcastRecord{
Intent intent;
ArrayList<ReceiverRecord> receivers;
}
HashMap<BroadcastReceiver, ArrayList<ReceiverRecord>> mReceivers = new HashMap<>();//注冊(cè)時(shí)保存receiver的對(duì)應(yīng)關(guān)系
HashMap<String, ArrayList<ReceiverRecord>> mActions = new HashMap<>();//注冊(cè)時(shí)保存action和receiver對(duì)應(yīng)關(guān)系,方便發(fā)送廣播時(shí)查找對(duì)應(yīng)的ReceiverRecord,一對(duì)多的關(guān)系
ArrayList<BroadcastRecord> mPendingBroadcasts = new ArrayList<>();//正在執(zhí)行的BroadcastReceiver
注冊(cè)時(shí)
registerReceiver(BroadcastReceiver receiver,IntentFiler filter);
保存receiver和ReceiverRecord的對(duì)應(yīng)關(guān)系:一對(duì)多(因?yàn)橐粋€(gè)receiver可以對(duì)應(yīng)多個(gè)intentFilter)
保存action和ReceiverRecord的對(duì)應(yīng)關(guān)系:一對(duì)多(因?yàn)橐粋€(gè)action可以對(duì)應(yīng)多個(gè)receiver)
發(fā)送廣播
sendBroadcast(Intent intent)
從intent中獲取action匹配的receiver,然后將receiver加入到執(zhí)行集合中,發(fā)送handler消息開始執(zhí)行
反注冊(cè)
unregisterReceiver(BroadCastReceiver receiver)
從兩個(gè)map集合中刪除對(duì)應(yīng)的receiver