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的源码如下:
 private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }
 
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();
    }
以上代码最终会执行到 return new Message();
Message的构造函数为空
    public Message() {
    }

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

所以当删除消息ID值为0的消息时,如:
 
  
    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的消息, 如:
 
  
        enum MSG_ID {
		ID_NOT_USE,
		ID_FIRST,
		ID_SECOND,
		ID_THRED
	}


 
  

你可能感兴趣的:(Android)