- public class BleService extends Service {
- public static final String TAG = "BleService";
- static final int MSG_REGISTER = 1;
- static final int MSG_UNREGISTER = 2;
- private final Messenger mMessenger;
- private final List<Messenger> mClients =
- new LinkedList<Messenger>();
- public BleService() {
- mMessenger = new Messenger(
- new IncomingHandler(this));
- }
- @Override
- public IBinder onBind(Intent intent) {
- return mMessenger.getBinder();
- }
- private static class IncomingHandler extends Handler {
- private final WeakReference<BleService> mService;
- public IncomingHandler(BleService service) {
- mService = new WeakReference<BleService>(service);
- }
- @Override
- public void handleMessage(Message msg) {
- BleService service = mService.get();
- if (service != null) {
- switch (msg.what) {
- case MSG_REGISTER:
- service.mClients.add(msg.replyTo);
- Log.d(TAG, "Registered");
- break;
- case MSG_UNREGISTER:
- service.mClients.remove(msg.replyTo);
- Log.d(TAG, "Unegistered");
- break;
- default:
- super.handleMessage(msg);
- }
- }
- }
- }
首先,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判断因为父类的实例如果被垃圾回收那么该引用将为空,但如果它不为空,那么我们可以以与非静态内部类完全相同的方式使用该实例的引用。