Android中Memory Leak原因分析及解決辦法
在Android開發(fā)過程中,我們經(jīng)常碰到的情況就是在我們不清楚為什么情況下,程序突然出現(xiàn)Crash了。其中有一類日志相信大家都經(jīng)常碰到過,這類日志就是OOM相關(guān)的日志。這類日志除了我們知道的Bitmap操作的時候會經(jīng)常導(dǎo)致,還有一種隱藏的較深的原因就是內(nèi)存泄露(Memory Leak)。
內(nèi)存泄露產(chǎn)生原因和影響: 原因:當(dāng)一個Object不再需要的時候,本該被GC回收時,但是因為另一個正在使用的Object持有它導(dǎo)致不能正常的被回收,本該被回收的對象不能回收,還存留在堆內(nèi)存中,此時就產(chǎn)生了內(nèi)存泄露。影響:Android系統(tǒng)能夠為每個應(yīng)用程序分配的內(nèi)存是有限的,當(dāng)一個應(yīng)用程序中產(chǎn)生的內(nèi)存泄露過多的時候,會難免導(dǎo)致應(yīng)用程序需要的內(nèi)存超過限額而導(dǎo)致內(nèi)存溢出使得應(yīng)用程序崩潰。 內(nèi)存泄露的檢測方式
推薦使用 LeakCanary 工具來檢測應(yīng)用程序是否存在內(nèi)存泄露。LeakCanary是由 Square 開源的一款輕量級的第三方內(nèi)存泄漏檢測工具,當(dāng)檢測到程序中產(chǎn)生內(nèi)存泄漏時,它將以最直觀的方式告訴我們哪里產(chǎn)生了內(nèi)存泄漏和導(dǎo)致誰泄漏了而不能被回收。
如何避免內(nèi)存泄露
1、合理使用單例模式。
單例的靜態(tài)特性使得其生命周期和應(yīng)用的生命周期一樣長。
如圖,我們先聲明一個單例對象:

然后在Activity使用的時候,習(xí)慣性的傳一個this:

集成了LeakCanary后測試,發(fā)現(xiàn)內(nèi)存泄露了:

解決方案:
一般情況下,改成如下圖的寫法就可以了,因為單例的生命周期和應(yīng)用的一樣長,這樣就防止了內(nèi)存泄漏。:

總結(jié):單例模式造成泄漏的原因是擁有更長生命周期的對象持有短生命周期對象的強(qiáng)引用。
2、使用資源時注意資源的關(guān)閉
一般情況下,容易產(chǎn)生內(nèi)存泄露的資源主要為:File,Cursor,Stream,Bitmap,BroadcastReceiver等,這些資源在使用時建議及時關(guān)閉,否則當(dāng)這些資源沒有及時回收的時候,內(nèi)存泄露也就產(chǎn)生了。針對這些資源使用,給如下建議:
BroadcastReceiver 在register之后,需要在適當(dāng)?shù)臅r機(jī)unregister Cursor、Stream、File 這類資源類型的對象往往會使用一些Cache,所以我們在不使用的時候,應(yīng)該及時關(guān)閉,以便Cache被及時回收。如果我們僅僅把它的引用設(shè)置為null,而不去關(guān)閉他們,往往會造成內(nèi)存泄露。一般建議是先close()后置為null。 Bitmap在不使用的時候,調(diào)用recycle()方法。目前 Android 2.3版本以后,不需要我們手動去這樣做的,這里也就是簡單的交代一下。
3、 合理使用Handler避免內(nèi)存泄露
在我們使用Handler的時候,經(jīng)常看到編輯器提示我們Handler可能會造成內(nèi)存泄露,一般在這種情況下,我們可以將Handler獨(dú)立出來或者使用靜態(tài)內(nèi)部類,這樣可以避免內(nèi)存泄露。
這樣做的原因是:非靜態(tài)內(nèi)部類會潛在的持有它所屬的外部類的引用,但是靜態(tài)內(nèi)部類是不會的。
4、 合理的使用WeakReference來引用外部類的成員變量
我們可以使用WeakReference來規(guī)避好多潛在的內(nèi)存泄露的問題,但是并不表明WeakReference就是解決內(nèi)存泄露的金鑰匙。是否使用WeakReference主要取決于對當(dāng)前對問題的理解,這需要我們對問題的的建模思想。
相關(guān)文章
Android編程之截屏實現(xiàn)方法(包括scrollview與listview)
這篇文章主要介紹了Android編程之截屏實現(xiàn)方法,包括截取scrollview與listview屏幕的相關(guān)技巧,以及截屏圖片的生成與保存技巧,需要的朋友可以參考下2015-11-11
android 仿微信demo——注冊功能實現(xiàn)(服務(wù)端)
本篇文章主要介紹了微信小程序-閱讀小程序?qū)嵗?,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望能給你們提供幫助2021-06-06
Flutter狀態(tài)管理Provider的使用示例詳解
這篇文章主要為大家介紹了Flutter狀態(tài)管理Provider的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
android基于socket的局域網(wǎng)內(nèi)服務(wù)器與客戶端加密通信
本篇文章主要介紹了android基于socket的局域網(wǎng)內(nèi)服務(wù)器與客戶端加密通信,這里整理了詳細(xì)的代碼,有需要的小伙伴可以參考下。2017-04-04
Android實現(xiàn)調(diào)用手機(jī)攝像頭錄像限制錄像時長
這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)調(diào)用手機(jī)攝像頭錄像限制錄像時長,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03
Android原生定位服務(wù)LocationManager
這篇文章主要為大家介紹了Android原生定位服務(wù)LocationManager實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
詳解Android Material Design自定義動畫的編寫
這篇文章主要介紹了詳解Android Material Design自定義動畫的編寫,其中對Activity的過渡動畫進(jìn)行了重點講解,需要的朋友可以參考下2016-04-04

