[原創]Android Handler使用Message的一個注意事項


最近發現了一個莫名其妙的問題,在使用Handler.post(Runnable)這個接口時,Runnable有時候沒有運行,非常奇怪,后來發現是因為調用Handler.removeMessage()時,what參數傳的0,導致Runnable所在的Message被remove了,下面看下源碼。

 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源碼:

先看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刪除了,所以導致了之前看到的詭異問題。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM