关于Handler.removemessages方法

https://www.jianshu.com/p/737646300fce

在阅读老人的源码中,发现以下代码片段


private handleMessage(Message msg) {
    switch(msg.what) {
        case ACTION_XXX:
            // do something...
            this.removeMessages(ACTION_XXX);
            break;

            //other cases
        }
} 

1. 猜想

初步猜测其作用是为了处理某消息后,清除在消息队列中等待的同类消息,以达到防止在处理过程中重复发送的目的

2. 验证

于是写一个demo验证之(因为上述源码触发效果过为复杂,所以不用此进行验证)


mHandler.setHandlerCallBack(new MyHandler.MyHandlerCallBack() {
    @Override
    public void handleMessage(Message message) {
        Log.i(TAG, "handleMessage: " + message.arg1);
        if (message.what == ACTION_ODD) {
            mMyHandler.removeMessages(ACTION_ODD);
        }
    }
});

mButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Message message = Message.obtain();
        message.what = number % 2 == 0 ? ACTION_EVEN : ACTION_ODD;
        message.arg1 = number;
        
        // 将handleMessage延迟1s调用
        mHandler.sendMessageDelayed(message, 1000);
        number++;
    }
});

快速点击Button后,观察log日志输出

02-16 10:51:08.787 17454-17454/com.daijie.handlerapplication I/MainActivity: handleMessage: 0
02-16 10:51:08.958 17454-17454/com.daijie.handlerapplication I/MainActivity: handleMessage: 1
02-16 10:51:09.112 17454-17454/com.daijie.handlerapplication I/MainActivity: handleMessage: 2
02-16 10:51:09.489 17454-17454/com.daijie.handlerapplication I/MainActivity: handleMessage: 4
02-16 10:51:09.762 17454-17454/com.daijie.handlerapplication I/MainActivity: handleMessage: 6
02-16 10:51:10.100 17454-17454/com.daijie.handlerapplication I/MainActivity: handleMessage: 8
02-16 10:51:10.237 17454-17454/com.daijie.handlerapplication I/MainActivity: handleMessage: 9

3. 推论

从日志输出可以得知偶数全部被输出,而1~9中的奇数被过滤了
可以推断handleMessage在输出Message.what==1的log结束后,调用Handler.removeMessages将Message.what为ACTION_ODD从消息队列中移除,所以中间的消息被过滤掉了。

4. 查看源码

查看源码是最好的验证方式,所以先查看Handler的removeMessages方法源码


// Handler.java
public final void removeMessages(int what) {
    mQueue.removeMessages(this, what, null);
}

可以看出,这里实际上是移除消息队列的message,再看看MessageQueue中的removeMessages方法源码


// MessageQueue.java
void removeMessages(Handler h, int what, Object object) {
    if (h == null) {
        return;
    }

    synchronized (this) {
         Message p = mMessages;

        // 原代码注释,Remove all messages at front.
        // 根据上面传入的参数,p!=null成立,p.target == h成立,object == null 成立
        // 即此处可等同为p.what == what
        // 此处代码即找到第一个p.what == what的消息并将其移除
        while (p != null && p.target == h && p.what == what
               && (object == null || p.obj == object)) {
            Message n = p.next;
            mMessages = n;
            p.recycleUnchecked();
            p = n;
        }

        // Remove all messages after front.
        // 此处即为移除找到第一个后的Message
        while (p != null) {
            Message n = p.next;
            if (n != null) {
                // 同上,此处也可以等同为p.what == what
                if (n.target == h && n.what == what
                    && (object == null || n.obj == object)) {
                    Message nn = n.next;
                    n.recycleUnchecked();
                    p.next = nn;
                    continue;
                }
            }
            p = n;
        }
    }
}

由源码中可以看出,MessageQueue将Message.what与函数传入的what相同的Message从队列中移除,和推论相符


这是本人第一次进行探讨,如有什么错误,请在评论区进行纠正。



作者:呆呆李宇杰
链接:https://www.jianshu.com/p/737646300fce
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值