android.os.Handler.removeMessages doesn't work when boxing value type as msg.obj

主宰稳场 提交于 2019-12-13 20:09:48

问题


(NOTE: I am re-writing my question because my first version was inaccurate).

Given the following code:

Handler handler = new Handler();
Message msg = handler.obtainMessage(12345, 67890L);
handler.sendMessageDelayed(message, 10000);
...
handler.removeMessages(12345, 67890L);

The problem is that the message still fires 10 seconds after I sent it!

Why isn't handler.removeMessages removing the message?


回答1:


The problem is the auto-boxing of the long to a Long Object.

In the debugger of MessageQueue void removeMessages(Handler h, int what, Object object):

638: // Remove all messages after front.
639: while (p != null) {
640:     Message n = p.next;
641:     if (n != null) {
642:         if (n.target == h && n.what == what
643:             && (object == null || n.obj == object)) {
644:             Message nn = n.next;
645:             n.recycleUnchecked();
646:             p.next = nn;
647:             continue;
648:         }
649:     }
650:     p = n;
651: }

At line 643:

object = {java.lang.Long@4686} "67890"  
n.obj = {java.lang.Long@4688} "67890"

So, in my case the comparison always fails because it is comparing instances, and my boxed value instances are always different.

Still, I would have expected the under-the-covers implementation of removeMessages to be the following:

// Remove all messages after front.
while (p != null) {
    Message n = p.next;
    if (n != null) {
        if (n.target == h && n.what == what
            && (object == null || object == n.obj || object.equals(n.obj))) {
            Message nn = n.next;
            n.recycleUnchecked();
            p.next = nn;
            continue;
        }
    }
    p = n;
}

My fix is to do something like this:

LongSparseArray<Object> objects = new LongSparseArray<>();
Handler handler = new Handler();

void sendMessageDelayed(int what, long key, long delayMillis)
{
    Object object = key;
    objects.put(key, object);
    Message msg = handler.obtainMessage(what, object);
    handler.sendMessageDelayed(msg, delayMillis);
}

void removeMessages(int what, long key)
{
    Object object = objects.get(key);
    if (object != null) {
        handler.removeMessages(what, object);
        objects.remove(key);
    }
}

sendMessageDelayed(12345, 67890L, 10000);
...
removeMessages(12345, 67890L);

Pv



来源:https://stackoverflow.com/questions/36190851/android-os-handler-removemessages-doesnt-work-when-boxing-value-type-as-msg-obj

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!