关于静态内部类结合WeakReference避免内存泄露,同时可访问外部类的成员

来源:互联网 发布:c语言浮点数精度控制 编辑:程序博客网 时间:2024/05/22 04:41
  1. public class BleService extends Service {  
  2.     public static final String TAG = "BleService";  
  3.     static final int MSG_REGISTER = 1;  
  4.     static final int MSG_UNREGISTER = 2;  
  5.     private final Messenger mMessenger;  
  6.     private final List<Messenger> mClients =   
  7.         new LinkedList<Messenger>();  
  8.   
  9.     public BleService() {  
  10.         mMessenger = new Messenger(  
  11.             new IncomingHandler(this));  
  12.     }  
  13.   
  14.     @Override  
  15.     public IBinder onBind(Intent intent) {  
  16.         return mMessenger.getBinder();  
  17.     }  
  18.   
  19.     private static class IncomingHandler extends Handler {  
  20.         private final WeakReference<BleService> mService;  
  21.   
  22.         public IncomingHandler(BleService service) {  
  23.             mService = new WeakReference<BleService>(service);  
  24.         }  
  25.   
  26.         @Override  
  27.         public void handleMessage(Message msg) {  
  28.             BleService service = mService.get();  
  29.             if (service != null) {  
  30.                 switch (msg.what) {  
  31.                     case MSG_REGISTER:  
  32.                         service.mClients.add(msg.replyTo);  
  33.                         Log.d(TAG, "Registered");  
  34.                         break;  
  35.                     case MSG_UNREGISTER:  
  36.                         service.mClients.remove(msg.replyTo);  
  37.                         Log.d(TAG, "Unegistered");  
  38.                         break;  
  39.                     default:  
  40.                         super.handleMessage(msg);  
  41.                 }  
  42.             }  
  43.         }  
  44.     }  

      基本代码非常简单但仍有一些细微之处值得去解释

     首先,InnerHandler 声明为静态。不要试图以一个非静态内部类来实现这个,否则会泄漏内存(leaking memory),这可能非常严重。这是因为一个类的非静态内部类可以持有一个该类的实例,并可以直接访问其成员变量和方法。简单来说,Java垃圾收集器将不会破坏被其他对象引用的对象(实际上比这更复杂一点,但也足够解释所发生的情况)。该Handler的父类实例是一个Service对象(一个Android Context),所以如果有任意一个对象持有该Handler实例的引用,都将隐式地阻止该Service对象被垃圾回收掉。这就是所谓的“Context  leak (上下文泄漏)”。它也是一个非常糟糕的事情,因为上下文可能相当大。

(译者注:关于“Context Leak”更多的介绍请查看http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html)

   我们避免上下文泄漏的方法是始终将内部类声明为静态,if they are declared within classes which subclass Context (不知道该怎么翻译)。 这也意味着我们已经失去了使用内部类的一个主要优点:访问父类属性和(or或)方法的能力。但我们可以很容易地通过使用WeakReference(弱引用)来克服这一点。弱引用可以使我们保持对一个对象的引用,并且不会阻止它被垃圾回收机制回收。

 所以我们的InnerHandler类被构造成拥有一个包裹在WeakReference对象中的它父类的实例的引用。而不是直接拥有其父类的引用。这样InnerHandler可以调用 WeakReference 的get()方法获取其父类实例的引用。我们需要做一个null判断因为父类的实例如果垃圾回收那么该引用将为但如果它不为空,那么我们可以以与非静态内部类完全相同的方式使用该实例的引用


阅读全文
0 0
原创粉丝点击