在阅读老人的源码中,发现以下代码片段
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从队列中移除,和推论相符
这是本人第一次进行探讨,如有什么错误,请在评论区进行纠正。
网友评论