Android Handler removeMessages引发postDelayed失效的问题

最近遇到一个使用Handler removeMessages时使 使用boolean postDelayed(Runnable r, long delayMillis)函数post的Runnable也被删除而没有执行的问题,具体如下:

public class MainActivity extends Activity {
	static final String TAG_STRING = "Main";
	enum MSG_ID {
		ID_FIRST,
		ID_SECOND,
		ID_THRED
	}
	
	Handler mHandler = new Handler() {
		@Override 
		 public void handleMessage(Message msg) {
			Log.e(TAG_STRING, " handleMessage what = " + msg.what);			
	    }
	};
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e(TAG_STRING, "onCreate");
        
        mHandler.sendEmptyMessageDelayed(MSG_ID.ID_FIRST.ordinal(), 1000);
        mHandler.postDelayed(new Runnable() {			
			@Override
			public void run() {
				Log.e(TAG_STRING, "run");
			}
		}, 1000);
        
        mHandler.removeMessages(MSG_ID.ID_FIRST.ordinal());
    }    
}

mHandler.removeMessages(MSG_ID.ID_FIRST.ordinal());这行被屏蔽时,打印如下:
01-03 04:08:36.362: E/Main(663): onCreate
01-03 04:08:37.372: E/Main(663):  handleMessage what = 0
01-03 04:08:37.372: E/Main(663): run

mHandler.removeMessages(MSG_ID.ID_FIRST.ordinal());这行被打开时,打印如下
01-03 04:12:28.372: E/Main(709): onCreate

我们看到  mHandler.postDelayed的Runnable也没有执行了。

查看一下postDelayed的源码,如下:
public final boolean postDelayed(Runnable r, long delayMillis)
{
    return sendMessageDelayed(getPostMessage(r), delayMillis);
}

getPostMessage的源码如下:
<pre name="code" class="java"> private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }
 
<pre name="code" class="java" style="font-size: 14px;">Message.obtain()的代码如下:
 
     public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }
以上代码最终会执行到 <span style="font-family: 'Microsoft YaHei';">return new Message();</span>
Message的构造函数为空
    public Message() {
    }

那么Message的what成员被默认赋值为0.

所以当删除消息ID值为0的消息时,如:
 
<pre name="code" class="java">    mHandler.removeMessages(MSG_ID.ID_FIRST.ordinal());
使用postDelayed post出去的Runnable, 如果还没被执行, 也会被删除掉。与此相同的还有
    public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
    {
        return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
    }

为了避免以上问题的发生, 用户应该避免使用消息ID值为0的消息, 如:
 
<pre name="code" class="java">        enum MSG_ID {
		ID_NOT_USE,
		ID_FIRST,
		ID_SECOND,
		ID_THRED
	}


 


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值