在Android的线程通讯当中,使用频率最多的就是Android的消息处理机制(Handler.send()、View.post()、Asynctask.excute()等等都使用到了消息处理机制)。Android中UI线程默认实现了该机制,其它工做线程要想跟UI线程同样拥有该机制,就必须人为去实现该机制,该机制的实现也至关简单暂且忽略。对于Android里的消息处理,涉及到Handler,Looper,Message,Message Queue等概念。java
为了便于理解Message泄漏,首先看一段Message的源代码:android
// sometimes we store linked lists of these things /*package*/ Message next; private static final Object sPoolSync = new Object(); private static Message sPool; private static int sPoolSize = 0; private static final int MAX_POOL_SIZE = 50; /** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; sPoolSize--; return m; } } return new Message(); }
从以上代码能够看到Message类有一个全局的消息池,池的大小为50,用于存放Message对象。Message引发泄漏的问题就出在这个全局的消息池。咱们知道Java的回收是由GC来进行的,而当咱们强引用着一个对象时,GC是不会将这个对象回收的。正好这个全局的消息池,里面存储的Message必然是一个强引用。形成Message泄漏的一个最大的根源是Message的obj字段,这个字段是Object类型的,所以obj的byte数是能够很大的。安全
有些人可能会说,那我对obj这个参数作弱引用让GC可以回收好不就得了。这个方法虽然能解决GC的回收,可是有一个致命的问题,就是弱应用是极不安全的,GC想要何时回收弱应用对象就何时回收。因此咱们应该换一个解决方方法,处理完一个Message就从全局当中移除一个。对于这个实现,Android的Handler有三个暴露的方法可供使用,removeMessages(int what)、removeMessages(int what, Object object)和removeCallbacksAndMessages(Object token)。具体使用可见以下代码:ide
@Override public void handleMessage(android.os.Message msg) { if (msg == null) { return; } removeXXXXX(); } }
removeMessages(int what)和removeMessages(int what, Object object)会调用MessageQueue的removeMessages(Handler h, int what, Object object),该方法源码以下:oop
void removeMessages(Handler h, int what, Object object) { if (h == null) { return; } synchronized (this) { Message p = mMessages; // Remove all messages at front. while (p != null && p.target == h && p.what == what && (object == null || p.obj == object)) { Message n = p.next; mMessages = n; p.recycle(); p = n; } // Remove all messages after front. while (p != null) { Message n = p.next; if (n != null) { if (n.target == h && n.what == what && (object == null || n.obj == object)) { Message nn = n.next; n.recycle(); p.next = nn; continue; } } p = n; } } }
removeCallbacksAndMessages(Object token)会调用MessageQueue的removeCallbacksAndMessages(Handler h, Object object)方法,该方法源码以下:post
void removeCallbacksAndMessages(Handler h, Object object) { if (h == null) { return; } synchronized (this) { Message p = mMessages; // Remove all messages at front. while (p != null && p.target == h && (object == null || p.obj == object)) { Message n = p.next; mMessages = n; p.recycle(); p = n; } // Remove all messages after front. while (p != null) { Message n = p.next; if (n != null) { if (n.target == h && (object == null || n.obj == object)) { Message nn = n.next; n.recycle(); p.next = nn; continue; } } p = n; } } }