最近遇到一个使用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
}