Android Handler正確使用姿勢


以前項目中會遇到的內存泄漏的問題,其中就有Handler使用姿勢不正確造成的。修改過后沒有總結寫篇博客記錄,前幾天看書看到這里,順便寫篇博客記錄一下。

容易造成內存泄漏的一種Handler使用方法:將Handler聲明為Activity的內部類。在Java語言中,非靜態內部類會持有外部類的一個隱試引用,這樣就可能造成外部類無法被垃圾回收。而導致內存泄漏。

 

[java]  view plain  copy
 
  1. private final Handler handler = new Handler(){  
  2.         @Override  
  3.         public void handleMessage(Message msg) {  
  4.             super.handleMessage(msg);  
  5.             // ...  
  6.         }  
  7.     };  


那么正確的使用就是:

 

1.將Handler聲明為靜態內部類。並持有外部類的若引用。

2.在子線程中使用Handler,這是需要我們自己創建一個Looper對象。

下面代碼介紹一下第一種用法:

 

[java]  view plain  copy
 
  1. /** 
  2.  *  正確使用Handler方式 
  3.  */  
  4. public class HandlerActivity extends AppCompatActivity {  
  5.       
  6.   
  7.     private final MyHandler mHandler = new MyHandler(this);  
  8.   
  9.     /** 
  10.      * 靜態的匿名內部類不會持有外部類的引用 
  11.      */  
  12.     private static final Runnable sRunnable = new Runnable() {  
  13.         @Override  
  14.         public void run() {  
  15.             // ...你的操作  
  16.   
  17.         }  
  18.     };  
  19.   
  20.   
  21.     @Override  
  22.     protected void onCreate(Bundle savedInstanceState) {  
  23.         super.onCreate(savedInstanceState);  
  24.         setContentView(R.layout.activity_handler);  
  25.   
  26.         mHandler.post(sRunnable);  
  27.     }  
  28.   
  29.   
  30.     /** 
  31.      * 聲明一個靜態的Handler內部類,並持有外部類的弱引用 
  32.      */  
  33.     private static class MyHandler extends Handler{  
  34.   
  35.         private final WeakReference<HandlerActivity> mActivty;  
  36.   
  37.         private MyHandler(HandlerActivity mActivty) {  
  38.             this.mActivty = new WeakReference<HandlerActivity>(mActivty);  
  39.         }  
  40.   
  41.         @Override  
  42.         public void handleMessage(Message msg) {  
  43.             super.handleMessage(msg);  
  44.             HandlerActivity activity = mActivty.get();  
  45.             if (activity != null){  
  46.                 // ....  
  47.   
  48.             }  
  49.         }  
  50.     }  
  51.   
  52. }  

 

上面在Activity使用就需要聲明一個內部類,下面再看一個,將自定義Handler抽出去,也同樣達到效果的小栗子:

1.首先創建一個類,通過泛型將實例傳入

 

[java]  view plain  copy
 
  1. public class UIHandler<T> extends Handler {  
  2.   
  3.     protected WeakReference<T> ref;  
  4.   
  5.     public UIHandler(T cls){  
  6.         ref = new WeakReference<T>(cls);  
  7.     }  
  8.   
  9.     public T getRef(){  
  10.         return ref != null ? ref.get() : null;  
  11.     }  
  12. }  


2.看下activity中使用,直接用myHandler對象發送message即可。

 

 

[java]  view plain  copy
 
  1. private static class UIMyHandler extends UIHandler<HandlerActivity>{  
  2.   
  3.         public UIMyHandler(HandlerActivity cls) {  
  4.             super(cls);  
  5.         }  
  6.   
  7.         @Override  
  8.         public void handleMessage(Message msg) {  
  9.             super.handleMessage(msg);  
  10.             HandlerActivity activity = ref.get();  
  11.             if (activity != null){  
  12.                 if (activity.isFinishing())  
  13.                     return;  
  14.   
  15.                 switch (msg.what){  
  16.   
  17.                     case 1:{  
  18.   
  19.                         break;  
  20.                     }  
  21.   
  22.                     // ...  
  23.   
  24.                 }  
  25.   
  26.             }  
  27.         }  
  28.     }  
  29.   
  30.     private UIMyHandler myHandler = new UIMyHandler(this);  

 

最后在簡單介紹一下,Java弱引用以及軟引用還有虛引用。

 

個人認為,如果只是想避免OutOfMemory異常的發生,則可以使用軟引用。若果對於應用的性能更在意,想盡快回收一些占用內存比較大的對象,則可以使用弱引用。
          和弱引用功能類似的是WeakHashMap,他對於一個給定的鍵,其映射的存在並不阻止垃圾回收器對該鍵的回收,回收以后,其條目從映射中有效的一處。WeakHashMap使用ReferenceQueue實現的這種機制。
          java.lang.ref包中提供了幾個類:SoftReference類—>軟引用;
                                                              WeakReference類—>弱引用;
                                                              PhantomReference—>虛引用;(相當於沒有持有引用,形同虛設,隨時可能被回收)
          弱引用實踐場景:自己定義Handler類采用弱引用方式,防止內存泄漏。
          軟引用場景:應用中肯定會有很多的默認的圖片資源,會多次用到。如果每次都去獲取,讀取文件需要硬件操作,速度慢,導致性能降低。所以考慮將圖片緩存起來,需要時直接從內存中獲取,但是圖片占用內存空間很大,容易OutOfMemory。這時考慮軟引用。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM