Android中常見的內存泄漏彙總

本文原地址,非常不錯的文章

  • 集合類泄漏
    集合類如果僅僅有添加元素的方法,而沒有相應的刪除機制,導致內存被佔用。如果這個集合類是全局性的變量 (比如類中的靜態屬性,全局性的 map 等即有靜態引用或 final 一直指向它),那麼沒有相應的刪除機制,很可能導致集合所佔用的內存只增不減。比如上面的典型例子就是其中一種情況,當然實際上我們在項目中肯定不會寫這麼 2B 的代碼,但稍不注意還是很容易出現這種情況,比如我們都喜歡通過 HashMap 做一些緩存之類的事,這種情況就要多留一些心眼。

  • 單例造成的內存泄漏
    由於單例的靜態特性使得其生命週期跟應用的生命週期一樣長,所以如果使用不恰當的話,很容易造成內存泄漏。比如下面一個典型的例子,

    public class AppManager {
        private static AppManager instance;
        private Context context;
        private AppManager(Context context) {
            this.context = context;
        }
        public static AppManager getInstance(Context context) {
            if (instance == null) {
            instance = new AppManager(context);
        }
        return instance;
        }
    }

    這是一個普通的單例模式,當創建這個單例的時候,由於需要傳入一個Context,所以這個Context的生命週期的長短至關重要:

    1.如果此時傳入的是 Application 的 Context,因爲 Application 的生命週期就是整個應用的生命週期,所以這將沒有任何問題。

    2.如果此時傳入的是 Activity 的 Context,當這個 Context 所對應的 Activity 退出時,由於該 Context 的引用被單例對象所持有,其生命週期等於整個應用程序的生命週期,所以當前 Activity 退出時它的內存並不會被回收,這就造成泄漏了。
    正確的方式應該改爲下面這種方式:

    public class AppManager {
        private static AppManager instance;
        private Context context;
        private AppManager(Context context) {
            this.context = context.getApplicationContext();
            // 使用Application 的context
        }
        public static AppManager getInstance(Context context){
            if (instance == null) {
                instance = new AppManager(context);
            }
            return instance;
        }
    }

    或者這樣寫,連 Context 都不用傳進來了。在你的 Application 中添加一個靜態方法,getContext() 返回 Application 的 context,

public class AppManager {
    private static AppManager instance;
    private Context context = getApplicationContext();
    this.context = MyApplication.getContext();
    private AppManager() {

    }
    // 使用Application 的context
    public static AppManager getInstance() {
        if (instance == null) {
            instance = new AppManager();
        }
        return instance;
    }
    /**
      * 獲取全局的context
      * @return 返回全局context對象
    */
    public static Context getContext(){
        return context;
    }
}

  • 匿名內部類/非靜態內部類和異步線程
  • 匿名內部類
  • Handler 造成的內存泄漏
  • 儘量避免使用 static 成員變量
  • 避免 override finalize()
  • 資源未關閉造成的內存泄漏
  • 一些不良代碼造成的內存壓力
  • 總結
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章