This Handler class should be static or leaks might occur 解决办法

首先解释下这句话This Handler class should be static or leaks might occur,大致意思就是说:Handler类应该定义成静态类,否则可能导致内存泄露。

具体如何解决,在国外有人提出,如下:

Issue: Ensures that Handler classes do not hold on to a reference to an outer class

In Android, Handler classes should be static or leaks might occur. Messages enqueued on the application thread's MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well. To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class.

大体翻译如下:

Handler 类应该应该为static类型,否则有可能造成泄露。在程序消息队列中排队的消息保持了对目标Handler类的应用。如果Handler是个内部类,那 么它也会保持它所在的外部类的引用。为了避免泄露这个外部类,应该将Handler声明为static嵌套类,并且使用对外部类的弱应用。



为什么会是这样呢?

了解一下Handler

  1. 当Android程序第一次创建的时候,在主线程同时会创建一个Looper对象。Looper实现了一个简单的消息队列,一个接着一个处理Message对象。程序框架所有主要的事件(例如:屏幕上的点击时间,Activity生命周期的方法等等)都包含在Message对象中,然后添加到Looper的消息队列中,一个一个处理。主线程的Looper存在整个应用程序的生命周期内。
  2. 当一个Handler对象在主线程中创建的时候,它会关联到Looper的 message queue。Message添加到消息队列中的时候Message会持有当前Handler引用,当Looper处理到当前消息的时候,会调用Handler#handleMessage(Message).
  3. 在java中,no-static的内部类会 隐式的 持有当前类的一个引用。static的类则没有。

在什么地方引起了内存的泄露呢?再看看下面一段代码

  
  
  
  
  1. public class SampleActivity extends Activity { 
  2.  
  3.   private final Handler mHandler = new Handler() { 
  4.     @Override 
  5.     public void handleMessage(Message msg) { 
  6.       // ... 
  7.     } 
  8.   } 
  9.  
  10.   @Override 
  11.   protected void onCreate(Bundle savedInstanceState) { 
  12.     super.onCreate(savedInstanceState); 
  13.  
  14.     // 发送一个10分钟后执行的一个消息 
  15.     mHandler.postDelayed(new Runnable() { 
  16.       @Override 
  17.       public void run() { } 
  18.     }, 600000); 
  19.  
  20.     // 结束当前的Activity 
  21.     finish(); 
  22.   } 
  23.   

Activity结束后,在 Message queue 处理这个Message之前,它会持续存活着。这个Message持有Handler的引用,而Handler有持有Activity(SampleActivity)的引用,这个Activity所有的资源,在这个消息处理之前都不能也不会被回收,所以发生了内存泄露。

解决办法,看下面一段代码

使用范例:

[java]  view plain copy
  1. static class MyHandler extends Handler {  
  2.                 WeakReference<PopupActivity> mActivity;  
  3.      
  4.                 MyHandler(PopupActivity activity) {  
  5.                         mActivity = new WeakReference<PopupActivity>(activity);  
  6.                 }  
  7.      
  8.                 @Override  
  9.                 public void handleMessage(Message msg) {  
  10.                         PopupActivity theActivity = mActivity.get();  
  11.                         switch (msg.what) {  
  12.                         case 0:  
  13.                                 theActivity.popPlay.setChecked(true);  
  14.                                 break;  
  15.                         }  
  16.                 }  
  17.         }  
  18.      
  19.         MyHandler ttsHandler = new MyHandler(this);  
  20.         private Cursor mCursor;  
  21.      
  22.         private void test() {  
  23.                 ttsHandler.sendEmptyMessage(0);  
  24.         }  



[java]  view plain copy
  1. static class IncomingHandler extends Handler {  
  2.     private final WeakReference<UDPListenerService> mService;  
  3.    
  4.     IncomingHandler(UDPListenerService service) {  
  5.         mService = new WeakRference<UDPListenerService>(service);  
  6.     }  
  7.     @Override  
  8.     public void handleMessage(Message msg)  
  9.     {  
  10.          UDPListenerService service = mService.get();  
  11.          if (service != null) {  
  12.               service.handleMessage(msg);  
  13.          }  
  14.     }  
  15. }  




[java]  view plain copy
  1. static class MHandler extends Handler {  
  2.     WeakReference<OuterClass> outerClass;  
  3.   
  4.     MHandler(OuterClass activity) {  
  5.         outerClass = new WeakReference<OuterClass>(activity);  
  6.     }  
  7.   
  8.     @Override  
  9.     public void handleMessage(android.os.Message msg) {  
  10.         OuterClass theClass = outerClass.get();  
  11.         switch (msg.what) {  
  12.         case 0: {  
  13.             //使用theClass访问外部类成员和方法  
  14.             break;  
  15.         }  
  16.         default: {  
  17.             Log.w(TAG, "未知的Handler Message:" + msg.what);  
  18.         }  
  19.         }  
  20.   
  21.     }  
  22. }  

WeakReference则类似于可有可无的东西。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存,说白了就是一个没那么strong要求垃圾回收器将一个对象保留在内存中。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

参考文章:http://www.cnblogs.com/jevan/p/3168828.html

http://blog.csdn.net/jdsjlzx/article/details/8463428

http://mobile.51cto.com/abased-406284.htm

你可能感兴趣的:(内存泄漏,警告)