zoukankan      html  css  js  c++  java
  • [原创]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删除了,所以导致了之前看到的诡异问题。

  • 相关阅读:
    Java多线程——<八>多线程其他概念
    Java多线程——<七>多线程的异常捕捉
    逆向破解之160个CrackMe —— 022
    逆向破解之160个CrackMe —— 021
    逆向破解之160个CrackMe —— 020
    逆向破解之160个CrackMe —— 019
    逆向破解之160个CrackMe —— 018
    逆向破解之160个CrackMe —— 017
    逆向破解之160个CrackMe —— 016
    逆向破解之160个CrackMe —— 015
  • 原文地址:https://www.cnblogs.com/coding-way/p/5110125.html
Copyright © 2011-2022 走看看