Handler內存泄漏

Handler內存泄漏

  1. 關於Handler內存泄漏及解決辦法:
    • 緣由:java

      1. handler會持有activity的匿名引用 (由於內部類的緣由,具體參考內部類實現),當activity要被回收時,由於handler在作耗時操做而沒有被釋放,從而內存泄漏
      2. 實例化Handler對象後,它就會主動與主線程的Looper的消息隊列關聯起來,全部發送到消息隊列的Message都會擁有一個對Handler的引用,因此才由Looper處理消息時的回調Handler.handlerMessage(Message)來處理消息
    • public class SampleActivity extends Activity {
          private Handler mHandler = new Handler() {
              @Override
              public void handleMessage(Message msg) {
                  //...
              }
          }
      }
      複製代碼
    • 解決辦法:git

      • 將Handler設置爲靜態內部類(具體參考靜態內部類和內部類區別),並使使Handler持有對Activity的弱引用github

        public class SampleActivity extends Activity {
                 .......
              private static class MyHandler extends Handler {
                     private final WeakReference<SampleActivity> mActivity;
                     public MyHandler(SampleActivity activity) {
                         myActivity = new WeakReference<SampleActivity>(activity);
                     }
        	 		@Override
         	 		public void handleMessage(Message msg) {
         	 			SampleActivity activity = mActivity.get();
             			if (activity != null) {
         			...
        	 		}
              }
           }
        }
        複製代碼
      • 在activity生命週期onDestroy()中調用Handler.removeCallback()方法bash

        // 清空消息隊列,移除對外部類的引用
        @Override
        protected void onDestroy() {
            super.onDestroy();
            mHandler.removeCallbacksAndMessages(null);
        
        }
        //Handler源碼中removeCallbacksAndMessages()註釋含義
        /**
         * Remove any pending posts of callbacks and sent messages whose
         * <var>obj</var> is <var>token</var>.  If <var>token</var> is null,
         * all callbacks and messages will be removed.
         */
        public final void removeCallbacksAndMessages(Object token) {
            mQueue.removeCallbacksAndMessages(this, token);
        }
        複製代碼
      複製代碼

內部類實現

  1. 內部類和靜態內部類以及匿名內部類的應用
    • 內部類的優點:ide

      • 內部類方法能夠訪問蓋內定義所在做用域的數據,包括私有數據函數

      • 內部類能夠對同一個包中其餘類隱藏oop

      • 想定義一個回調函數並且不像編寫大量代碼時,使用匿名內部類比較簡潔post

    • 原理:this

      • 內部類的對象總有一個隱式引用,它指向了建立它的外部類對象spa

      • 編譯器修改了全部內部類的構造器,添加了一個外圍類的引用參數:

        public class Outer {
            ...
        class Inner {
            ...
            //Outer爲外部類,Inner爲內部類
            Outer out;
            public Inner(Outer outer) {
            out = outer;
        	}
        }
        }
        複製代碼
    • 靜態內部類: 使用內部類只是爲了把一個類隱藏在另外一個類的內部,並不須要內部類引用外圍類的對象。 所以能夠將內部類聲明爲static,以便取消產生的引用

參考: juejin.im/post/5ccaa9…

github.com/francistao/…

相關文章
相關標籤/搜索