最近發現了一個莫名其妙的問題,在使用Handler.post(Runnable)這個接口時,Runnable有時候沒有運行,很是奇怪,後來發現是由於調用Handler.removeMessage()時,what參數傳的0,致使Runnable所在的Message被remove了,下面看下源碼。java
1 class MyHandler extends Handler { 2 @Override 3 public void handleMessage(Message msg) { 4 switch (msg.what) { 5 case MSG_DO_SOME: 6 Log.i("zhoukewen", "what ==== 0........"); 7 break; 8 } 9 } 10 } 11 12 Handler h = new MyHandler(); 13 14 final int MSG_DO_SOME = 0; 15 16 public void onStartClick(View view) { 17 18 h.sendEmptyMessage(MSG_DO_SOME); 19 h.post(new Runnable() { 20 @Override 21 public void run() { 22 Log.i("zhoukewen", "runnable............"); 23 } 24 }); 25 h.removeMessages(MSG_DO_SOME); 26 }
情景大概如圖所示,開發者也許但願刪除what=MSG_DO_SOME的msg,但當SG_DO_SOME剛好等於0時,會連帶攜帶Runnable的msg也被刪除,咱們看下post源碼:ide
先看Handler.javapost
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()this
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()以後才能使用的,咱們看源碼:spa
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刪除了,因此致使了以前看到的詭異問題。code