Android內(nèi)存泄漏

內(nèi)存泄露就是指該被GC垃圾回收的募疮,由于有另外一個(gè)對(duì)象仍然在引用它,導(dǎo)致無(wú)法回收僻弹,造成內(nèi)存泄露阿浓,過(guò)多的內(nèi)存泄露會(huì)導(dǎo)致OOM。

一蹋绽、原因及優(yōu)化

1 非靜態(tài)內(nèi)部類(lèi)芭毙、匿名內(nèi)部類(lèi)

非靜態(tài)內(nèi)部類(lèi)、匿名內(nèi)部類(lèi) 都會(huì)持有外部類(lèi)的一個(gè)引用卸耘,如果有一個(gè)靜態(tài)變量引用了非靜態(tài)內(nèi)部類(lèi)或者匿名內(nèi)部類(lèi)退敦,導(dǎo)致非靜態(tài)內(nèi)部類(lèi)或者匿名內(nèi)部類(lèi)的生命周期比外部類(lèi)(Activity)長(zhǎng),就會(huì)導(dǎo)致外部類(lèi)在該被回收的時(shí)候鹊奖,無(wú)法被回收掉苛聘,引起內(nèi)存泄露,除非外部類(lèi)被卸載(JVM自帶的類(lèi)加載器所加載的類(lèi)忠聚,在虛擬機(jī)的生命周期中设哗,始終不會(huì)被卸載,除非使用自定義的類(lèi)加載器)两蟀。

優(yōu)化:
  • 將非靜態(tài)內(nèi)部類(lèi)网梢、匿名內(nèi)部類(lèi) 改成靜態(tài)內(nèi)部類(lèi),或者直接抽離成一個(gè)外部類(lèi)赂毯。
  • 如果在靜態(tài)內(nèi)部類(lèi)中战虏,需要引用外部類(lèi)對(duì)象拣宰,那么可以將這個(gè)引用封裝在一個(gè)WeakReference中。

2 Handler

主線程的Looper對(duì)象不斷從消息隊(duì)列中取出消息烦感,然后再交給Handler處理巡社。如果在Activity中定義Handler對(duì)象,那么Handler肯定持有Activty的引用手趣,而每個(gè)Message對(duì)象是持有Handler的引用的(Message對(duì)象的target屬性持有Handler引用)晌该,從而導(dǎo)致Message間接引用到了Activity。如果在Activty destroy之后绿渣,消息隊(duì)列中還有Message對(duì)象朝群,Activty是不會(huì)被回收的。當(dāng)然了中符,如果消息正在準(zhǔn)備(處于延時(shí)入隊(duì)期間)放入到消息隊(duì)列中也是一樣的姜胖。

優(yōu)化:
  • 將Handler放入單獨(dú)的類(lèi)或者將Handler放入到靜態(tài)內(nèi)部類(lèi)中(靜態(tài)內(nèi)部類(lèi)不會(huì)持有外部類(lèi)的引用)。如果想要在Handler內(nèi)部去調(diào)用所在的外部類(lèi)Activity淀散,可以在Handler內(nèi)部使用弱引用的方式指向所在Activity右莱,這樣不會(huì)導(dǎo)致內(nèi)存泄漏。
  • 在onDestory時(shí)档插,調(diào)用相應(yīng)的remove方法移除回調(diào)和刪除消息隧出。

弱引用相關(guān)請(qǐng)移步:Android強(qiáng)引用、弱引用阀捅、軟引用

3 靜態(tài)的View

有時(shí)胀瞪,當(dāng)一個(gè)Activity經(jīng)常啟動(dòng),但是對(duì)應(yīng)的View讀取非常耗時(shí)饲鄙,可以通過(guò)靜態(tài)View變量來(lái)保持對(duì)該Activity的rootView引用凄诞。這樣就可以不用每次啟動(dòng)Activity都去讀取并渲染View了。這確實(shí)是一個(gè)提高Activity啟動(dòng)速度的好方法忍级。
但是要注意帆谍,一旦View attach到Window上,就會(huì)持有一個(gè)Context(即Activity)的引用轴咱,而該View又是一個(gè)靜態(tài)變量汛蝙,所以導(dǎo)致Activity不被回收。

優(yōu)化:
  • 在使用靜態(tài)View時(shí)朴肺,需要確保在資源回收時(shí)窖剑,將靜態(tài)View detach掉。

4 監(jiān)聽(tīng)器(各種需要注冊(cè)的Listener戈稿、Watcher等)

當(dāng)需要使用系統(tǒng)服務(wù)(比如執(zhí)行某些后臺(tái)任務(wù)西土、為硬件訪問(wèn)提供接口等等系統(tǒng)服務(wù))時(shí),需要把Activity自己注冊(cè)到服務(wù)的監(jiān)聽(tīng)器中鞍盗,這會(huì)讓服務(wù)持有Activity的引用需了,如果沒(méi)有在Activity銷(xiāo)毀時(shí)取消注冊(cè)跳昼,那就會(huì)導(dǎo)致Activity泄漏。
例如:EditText的addTextChangeListener肋乍,如果在回調(diào)方法里有耗時(shí)操作鹅颊,可能會(huì)造成內(nèi)存泄露。

優(yōu)化:
  • 在onDestory時(shí)墓造,取消注冊(cè)挪略。
    比如:editText.removeTextChangedListener

5 WebView

在android 5.1及以上版本的代碼中,WebView可能會(huì)存在內(nèi)存泄露滔岳。
(原因可以參考這篇文章:https://blog.csdn.net/u013085697/article/details/53259116

優(yōu)化:
  • 在銷(xiāo)毀WebView前一定要onDetachedFromWindow,先將WebView從它的父View中移除再調(diào)用destroy方法挽牢。

6 單例造成的內(nèi)存泄漏

單例的靜態(tài)特性使得單例的生命周期和應(yīng)用的生命周期一樣長(zhǎng)谱煤,這就說(shuō)明了如果一個(gè)對(duì)象已經(jīng)不需要使用了,而單例對(duì)象還持有該對(duì)象的引用禽拔,那么這個(gè)對(duì)象將不能被正沉趵耄回收,這就導(dǎo)致了內(nèi)存泄漏睹栖。

7 線程死鎖

8 資源對(duì)象沒(méi)有關(guān)閉

當(dāng)打開(kāi)資源時(shí)硫惕,一般都會(huì)使用緩存。比如讀寫(xiě)文件資源野来、打開(kāi)數(shù)據(jù)庫(kù)資源恼除、使用Bitmap資源等等。當(dāng)不再使用時(shí)曼氛,應(yīng)該關(guān)閉它們豁辉,使得緩存內(nèi)存區(qū)域及時(shí)回收。雖然有些對(duì)象舀患,如果不去關(guān)閉徽级,它自己在finalize()函數(shù)中會(huì)自行關(guān)閉,但是這要等到GC回收時(shí)才關(guān)閉聊浅,這樣會(huì)導(dǎo)致緩存駐留一段時(shí)間餐抢。如果頻繁打開(kāi)資源,內(nèi)存泄漏帶來(lái)的影響就比較明顯了低匙。

9 屬性動(dòng)畫(huà)

在使用ValueAnimator或者ObjectAnimator時(shí)旷痕,如果沒(méi)有及時(shí)做cancel取消動(dòng)畫(huà),就可能造成內(nèi)存泄露顽冶。
因?yàn)樵赾ancel方法里苦蒿,最后調(diào)用了endAnimation(); ,在endAnimation里渗稍,有個(gè)AnimationHandler的單例佩迟,會(huì)持有屬性動(dòng)畫(huà)對(duì)象的引用团滥。

優(yōu)化:
  • 在onDestory時(shí),調(diào)用動(dòng)畫(huà)的cancel方法

10 其他的系統(tǒng)控件以及自定義View

在 Android Lollipop 之前使用 AlertDialog 可能會(huì)導(dǎo)致內(nèi)存泄漏报强,參考:https://blog.csdn.net/u012464435/article/details/50774580灸姊。

Dialog和DialogFragment在Android5.0以下的內(nèi)存泄漏,參考:https://www.cnblogs.com/endure/p/7664320.html秉溉,http://www.mamicode.com/info-detail-1753936.html力惯。

11 TimerTask


三、檢測(cè)工具

1 命令行查看內(nèi)存占用情況

adb shell dumpsys meminfo -a 包名

2 AS自帶的Monitors

展示內(nèi)存使用召嘶,及網(wǎng)絡(luò)父晶、CPU、GPU使用情況弄跌。

3 LeakCanary

隨應(yīng)用運(yùn)行甲喝,實(shí)時(shí)監(jiān)測(cè)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末铛只,一起剝皮案震驚了整個(gè)濱河市埠胖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌淳玩,老刑警劉巖直撤,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蜕着,居然都是意外死亡谋竖,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)承匣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)圈盔,“玉大人,你說(shuō)我怎么就攤上這事悄雅∏茫” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵宽闲,是天一觀的道長(zhǎng)众眨。 經(jīng)常有香客問(wèn)我,道長(zhǎng)容诬,這世上最難降的妖魔是什么娩梨? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮览徒,結(jié)果婚禮上狈定,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好纽什,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布措嵌。 她就那樣靜靜地躺著,像睡著了一般芦缰。 火紅的嫁衣襯著肌膚如雪企巢。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 50,050評(píng)論 1 291
  • 那天让蕾,我揣著相機(jī)與錄音浪规,去河邊找鬼。 笑死探孝,一個(gè)胖子當(dāng)著我的面吹牛笋婿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播顿颅,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼缸濒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了元镀?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤霎桅,失蹤者是張志新(化名)和其女友劉穎栖疑,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體滔驶,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡遇革,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了揭糕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萝快。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖著角,靈堂內(nèi)的尸體忽然破棺而出揪漩,到底是詐尸還是另有隱情,我是刑警寧澤吏口,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布奄容,位于F島的核電站,受9級(jí)特大地震影響产徊,放射性物質(zhì)發(fā)生泄漏昂勒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧益眉,春花似錦已球、人聲如沸往核。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)列肢。三九已至血柳,卻和暖如春官册,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背难捌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工膝宁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人根吁。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓员淫,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親击敌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子介返,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • Android 內(nèi)存泄漏總結(jié) 內(nèi)存管理的目的就是讓我們?cè)陂_(kāi)發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問(wèn)題。內(nèi)存泄漏...
    _痞子閱讀 1,627評(píng)論 0 8
  • 內(nèi)存管理的目的就是讓我們?cè)陂_(kāi)發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問(wèn)題沃斤。內(nèi)存泄漏大家都不陌生了圣蝎,簡(jiǎn)單粗俗的講,...
    宇宙只有巴掌大閱讀 2,361評(píng)論 0 12
  • Android 內(nèi)存泄漏總結(jié) 內(nèi)存管理的目的就是讓我們?cè)陂_(kāi)發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問(wèn)題衡瓶。內(nèi)存泄漏...
    apkcore閱讀 1,219評(píng)論 2 7
  • 內(nèi)存管理的目的就是讓我們?cè)陂_(kāi)發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問(wèn)題徘公。內(nèi)存泄漏大家都不陌生了,簡(jiǎn)單粗俗的講哮针,...
    DreamFish閱讀 791評(píng)論 0 5
  • 【Android 內(nèi)存泄漏】 引用: ★★★ 【知識(shí)必備】?jī)?nèi)存泄漏全解析关面,從此拒絕ANR,讓OOM遠(yuǎn)離你的身邊十厢,跟...
    Rtia閱讀 803評(píng)論 0 2