常見(jiàn)內(nèi)存泄漏場(chǎng)景

本文據(jù)《Android應(yīng)用性能最佳實(shí)踐優(yōu)化(羅彧成)》總結(jié)而成。

  1. 資源性對(duì)象未關(guān)閉
    資源性對(duì)象(如Cursor、File等)往往都用到緩存,在不使用時(shí),應(yīng)及時(shí)關(guān)閉它們,以便它們的內(nèi)存數(shù)據(jù)能夠及時(shí)回收。有些資源性對(duì)象,如SQLite Cursor,如果沒(méi)有手動(dòng)關(guān)閉它,在系統(tǒng)回收它時(shí)也會(huì)關(guān)閉之,但這樣的效率太低,還是建議不使用時(shí)立即手動(dòng)調(diào)用close()函數(shù),將其關(guān)閉,然后再置為null。在程序退出時(shí),一定要確保資源性對(duì)象已經(jīng)關(guān)閉。

  2. 注冊(cè)對(duì)象未注銷(xiāo)
    如果事件注冊(cè)后未注銷(xiāo),會(huì)導(dǎo)致觀察者列表中維持著對(duì)對(duì)象的引用,阻止垃圾回收,這一般發(fā)生在注冊(cè)廣播接收器、注冊(cè)觀察者等。

  3. 類(lèi)的靜態(tài)變量持有大數(shù)據(jù)對(duì)象
    靜態(tài)變量長(zhǎng)期維持對(duì)對(duì)象的引用,阻止垃圾回收,如果靜態(tài)變量持有大的數(shù)據(jù)對(duì)象,如Bitmap等,就很容易引起內(nèi)存不足等問(wèn)題。

  4. 非靜態(tài)內(nèi)部類(lèi)的靜態(tài)實(shí)例
    非靜態(tài)內(nèi)部類(lèi)會(huì)維持一個(gè)對(duì)外部類(lèi)實(shí)例的引用,如果非靜態(tài)內(nèi)部類(lèi)的實(shí)例是靜態(tài)的,就會(huì)間接長(zhǎng)期持有對(duì)外部類(lèi)的引用,阻止外部類(lèi)被系統(tǒng)回收。
    為避免這種情況發(fā)生,可以將內(nèi)部類(lèi)設(shè)置為靜態(tài)內(nèi)部類(lèi)將內(nèi)部類(lèi)抽取出來(lái)并封裝為一個(gè)單例,如果需要使用Context,在沒(méi)有特殊要求的情況下使用Application的Context,如果需要使用Activity的Context,就在用完之后置空讓GC可以回收,否則還是會(huì)內(nèi)存泄漏。

  5. Handler臨時(shí)性內(nèi)存泄漏
    Handler對(duì)象通過(guò)發(fā)送Message實(shí)現(xiàn)線程之間的交互,Message發(fā)出之后存儲(chǔ)在MessageQueue中,有些Message也不是馬上就被處理。在Message中存在一個(gè)target,它是Handler的一個(gè)引用,Message在Queue中存在的時(shí)間過(guò)長(zhǎng),就會(huì)導(dǎo)致Handler無(wú)法被回收。如果Handler是非靜態(tài)的,則會(huì)導(dǎo)致Activity或Service不會(huì)被回收。
    未避免這種內(nèi)存泄漏,需要做到以下兩個(gè)地方:

  1. 使用一個(gè)靜態(tài)Handler內(nèi)部類(lèi),然后對(duì)Handler持有的對(duì)象使用弱引用,這樣在回收時(shí),也可以回收Handler持有的對(duì)象。
  2. 在Activity的Destroy或者Stop時(shí),應(yīng)移除消息隊(duì)列中的消息,避免Looper線程的消息隊(duì)列中有待處理的消息需要處理。
  1. 容器中的對(duì)象沒(méi)清理造成的內(nèi)存泄漏
    有時(shí)會(huì)將一些對(duì)象的引用加入集合中,在不需要該對(duì)象時(shí),如果沒(méi)有把它的引用從集合中清理出去,這個(gè)集合就會(huì)越來(lái)越大。如果這個(gè)集合是static的,情況就更嚴(yán)重。

  2. WebView
    Android的WebView不僅存在很大的兼容性問(wèn)題,不同Android系統(tǒng)版本中的WebView也有較大差異。WebView都存在內(nèi)存泄漏的問(wèn)題,在應(yīng)用中只要使用一次WebView,內(nèi)存就不會(huì)被釋放掉。通常解決這個(gè)問(wèn)題的方法是為WebView開(kāi)啟獨(dú)立的一個(gè)進(jìn)程,使用AIDL與應(yīng)用的主線程進(jìn)行通信,WebView所在的進(jìn)程可以根據(jù)業(yè)務(wù)的需要選擇適合的時(shí)機(jī)進(jìn)行銷(xiāo)毀,達(dá)到正常釋放內(nèi)存的目的。

?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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