最近发现了一个莫名其妙的问题,在使用Handler.post(Runnable)这个接口时,Runnable有时候没有运行,非常奇怪,后来发现是因为调用Handler.removeMessage()时,what参数传的0,导致Runnable所在的Message被remove了,下面看下源码。

     class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_DO_SOME:
Log.i("zhoukewen", "what ==== 0........");
break;
}
}
} Handler h = new MyHandler(); final int MSG_DO_SOME = 0; public void onStartClick(View view) { h.sendEmptyMessage(MSG_DO_SOME);
h.post(new Runnable() {
@Override
public void run() {
Log.i("zhoukewen", "runnable............");
}
});
h.removeMessages(MSG_DO_SOME);
}

情景大概如图所示,开发者也许希望删除what=MSG_DO_SOME的msg,但当SG_DO_SOME恰好等于0时,会连带携带Runnable的msg也被删除,我们看下post源码:

先看Handler.java

    public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
} private final Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}

再看Message.obtain()

    public int what;

    public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
sPoolSize--;
return m;
}
}
return new Message();
}

可以看到,post(Runnable)时实际上也是创建一个Message,从代码中看到,该Message要不就是从sPool池中获取,要不就是new出来的,如果new出来的,其成员变量自然被初始化为0。如果从sPool中获取的话,sPool中的Message都是经过recycle()之后才能使用的,我们看源码:

    public void recycle() {
clearForRecycle(); synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
} /*package*/ void clearForRecycle() {
flags = 0;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
when = 0;
target = null;
callback = null;
data = null;
}

果然也是设置为0。所以,Handler.post(Runnable)其实就是生成一个what为0的Message,而当remove时,会删除所有what为0的Message,也就是吧Runnable的Message删除了,所以导致了之前看到的诡异问题。

[原创]Android Handler使用Message的一个注意事项的更多相关文章

  1. 转载《Android Handler、Message》

    之前也是由于周末通宵看TI3比赛,一直没找到时间写博客,导致已经有好久没更新了.惭愧!后面还会恢复进度,尽量保证每周都写吧.这里也是先恭喜一下来自瑞典的Alliance战队夺得了TI3的冠军,希望明年 ...

  2. Android Handler、Message完全解析,带你从源码的角度彻底理解

    之前也是由于周末通宵看TI3比赛,一直没找到时间写博客,导致已经有好久没更新了.惭愧!后面还会恢复进度,尽量保证每周都写吧.这里也是先恭喜一下来自瑞典的Alliance战队夺得了TI3的冠军,希望明年 ...

  3. Android handler真的是重新启动一个线程吗?

    我们说handler是开启了另外一个线程,而且看代码的话确实是这样,实现了runnable接口,这在java中就是开启了一个线程,但是情况中的是这样吗?我们不妨来做个试验,如下 import andr ...

  4. Android Handler之Message传递参数

    最近发现Message,发送消息可以传递参数,这个思路很好,所以写了一个例子,点击屏幕,给Activity发送一个消息,传递两个参数,并把这个activity销毁掉! 程序打开界面: 点击屏幕,销毁a ...

  5. Android Handler、Message、MessageQueue和Looper官方说明

    Handler官方说明 官方API文档:https://developer.android.google.cn/reference/android/os/Handler Handler允许您发送和处理 ...

  6. android handler ,message消息发送方式

    1.Message msg =  Message.obtain(mainHandler) msg.obj=obj;//添加你需要附加上去的内容 msg.what = what;//what消息处理的类 ...

  7. 与多线程结合使用的消息处理类Handler、Message

    1. 消息处理类——Handler 消息处理类(Handler)允许发送和处理Message或Runnable对象到其所在线程的MessageQueue中.Handerl有以下两个主要作用: 将Mes ...

  8. Android 异步消息处理机制 让你在深入了解 Looper、Handler、Message之间的关系

    转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/38377229 ,本文出自[张鸿洋的博客] 非常多人面试肯定都被问到过,请问And ...

  9. Android之消息机制Handler,Looper,Message解析

    PS:由于感冒原因,本篇写的有点没有主干,大家凑合看吧.. 学习内容: 1.MessageQueue,Looper,MessageQueue的作用. 2.子线程向主线程中发送消息 3.主线程向子线程中 ...

随机推荐

  1. android 用NineOldAndroid实现的弹出按钮

    NineOldAndroid 1.首先上效果图: 左边这张是没有点击button的时候的效果,   右边这张是点击button 后是以该button为圆的展开5个button

  2. [JAVA] 一个可以编辑、编译、运行Java简单文件的记事本java实现

    本来是Java课做一个仿windows记事本的实验,后来突然脑子一热,结果就给它加了一个编译运行Java文件的功能. 本工程总共大约3000行代码,基本上把所学的java界面.文件.控件的功能都包含在 ...

  3. 微软发布手机版 Sample Browser。7000多示例代码一手掌握

    今天早上,Sample Browser发布其全新的Windows Phone版本.至此,自2012年相继推出Desktop版.Visual Studio版,以及2013年推出Windows Store ...

  4. JSPatch中的OC高级语法

    1)多线程相关 dispatch_after dispatch_async dispatch_sync dispatch_get_main_queue dispatch_get_global_queu ...

  5. 基本hibernate DEMO

    Hibernate常用API: 1Configuration: 负责加载主配置文件信息,同时也加载映射关系文件信息. 2SessionFactory 负责创建Session对象. 3Session 数 ...

  6. Git 常用的命令总结(欢迎收藏备用)

    总结日常开发生产中常用的Git版本控制命令 ------------------------------main-------------------------------- <极客镇楼> ...

  7. JavaScript、for循环语句知识巩固,while(){}语句以及do{}while()语句以及switch()语句

    一.for循环语句练习 关于for循环存在的两个问题类型 穷举:在不知道什么情况下才真的寻要我们的结果,自能让我们一个个走一遍. 迭代:在现有的条件根据规律不断求解,中间情况,最终推测出来的结果 1. ...

  8. 在Windows下使用Nodist进行Node版本控制

    完全卸载Node.js 首先卸载Node.js应用程序 确认在C:\Program Files中没有Nodejs目录 确认在C:\Program Files (x86)没有Nodejs目录 删除C:\ ...

  9. Cocos2d-x3.x塔防游戏(保卫萝卜)从零开始(三)

    一.前提: 完成前一篇的内容. 具体参考:Cocos2d-x3.x塔防游戏(保卫萝卜)从零开始(二)篇 二.本篇目标: l  说说游戏中各种角色的动作.属性以及重构思路 l  进行代码重构让色狼大叔和 ...

  10. CoreOS实践(2)—在coreos上安装Kubernetes

    下载kubernetes sudo mkdir -p /opt/bin sudo wget https://storage.googleapis.com/kubernetes/binaries.tar ...