每日一問:Android 中內存泄漏都有哪些注意點?

內存泄漏對每一位 Android 開發必定是司空見慣,你們或多或少都確定有些許接觸。你們都知道,每個手機都有必定的承載上限,多處的內存泄漏堆積必定會堆積如山,最終出現內存爆炸 OOM。java

而這,也是極有可能在 Android 面試中一道常見的開放題。web

內存泄漏的根本緣由是一個長生命週期的對象持有了一個短生命週期的對象。若是你對垃圾回收機制有所瞭解,我想這個問題基本難不住你,由於知道了原理,天然不會去觸碰這些極易致使內存泄漏的雷區。面試

該題重在積累,不須要死記硬背,本身多總結便可。安全

1. 長生命週期對象持有 Activity

這基本是最多見的內存泄漏了,好比app

  • 內部類形式使用 Handler 同時發送延時消息,或者在 Handler 裏面執行耗時任務,在任務還沒完成的時候 Activity 須要銷燬。這時候因爲 Handler 持有 Activity 的強引用致使 Activity 沒法被回收。
  • 同理內部類形式的使用 AsyncTask 執行耗時任務也會致使內存泄漏的發生。
  • 單例做爲最長生命週期的對象,天然不該該持有 Activity 從而致使內存泄漏發生;

針對上面這種狀況,基本沒必要多說了,不要使用內部類或者匿名內部類作這樣的處理就行了,實際上 IDE 也會彈出警告,我想你們應該仍是都知道採用靜態內部類或者在銷燬頁面的時候使用相關方法移除處理的。框架

Activity 中匿名使用 Handler 實際上會致使 Handler 內部類持有外部類的引用,而 SendMessage() 的時候 Message 會持有 HandlerenqueueMessage 機制又會致使 MeassageQueue 持有 Message。因此當發送的是延遲消息那麼 Message 並不會當即的遍歷出來處理而是阻塞到對應的 Message 觸發時間之後再處理。那麼阻塞的這段時間中頁面銷燬必定會形成內存泄漏。ide

2. 各類註冊操做沒有對應的反註冊

這一點基本沒必要多說,相信你們剛剛開始學習廣播和 Service 的時候必定對此有所接觸,而後就是好比咱們經常使用的第三方框架 EventBus 也是同樣的。平時使用的時候注意在對應的生命週期方法中進行反註冊。佈局

3. Bitmap 使用完沒有注意 recycle()

Bitmap 做爲大對象,在使用完畢必定要注意調用 recycle() 進行回收。TypedArrayCursor、各類流同理,必定要在最後調用本身的回收關閉方法處理。學習

4. WebView 使用不當

WebView 是很是經常使用的控件,但稍有不注意也會致使內存泄漏。內存泄漏的場景: 不少人使用 Webview 都喜歡採用佈局引用方式, 這其實也是做爲內存泄漏的一個隱患。當 Activity 被關閉時,Webview 不會被 GC 立刻回收,而是提交給事務,進行隊列處理,這樣就形成了內存泄漏, 致使 Webview 沒法及時回收。this

目前所知的比較安全的方案是:

  • 在佈局中動態添加 WebView。
  • 採用下面的方法。
override fun onDestroy() {
    webView?.apply {
        val parent = parent
        if (parent is ViewGroup) {
            parent.removeView(this)
        }
        stopLoading()
        // 退出時調用此方法,移除綁定的服務,不然某些特定系統會報錯
        settings.javaScriptEnabled = false
        clearHistory()
        removeAllViews()
        destroy()
    }
}

5. 循環引用

循環引用致使內存泄漏比較少見,正常來說不會有人寫出 A 持有 B,B 持有 C,C 又持有A 這樣的代碼,不過總仍是須要注意。

總的來講,內存泄漏很常見,但檢測方式也不少。咱們的 Android Studio 自帶的 Monitors 就能夠幫咱們找到大部份內存問題,固然咱們也能夠採用譬如 LeakCanary 這樣的庫去作檢測。

相關文章
相關標籤/搜索