Handler sendMessage 與 obtainMessage (sendToTarget)比較


話說在工作中第一次接觸android 的Handler 的時候,不知道怎么去關注性能。

記得當時這么寫的:

Message msg = new Message()
msg.what = xxx;
msg.arg1  = xxx;
msg.arg2  = xxx;
handler.sendMessage(msg);

這樣寫也沒有絕得不好,反正當時項目的功能實現了。(性能上還可以)

后來沒事的時候看了看handler 的其他的方法,就看到了obtainMessage()這個方法.很奇怪,不知道為何還要出來的方法

本來上面的那段code 就能實現handler 的功能了,為什么還要出現他,后來百度google 一把,大家說 什么性能上有差別之

類的。。。。。結果可想而知(大部分的文章都是你抄我的我抄你的,技術就是這樣出來的。。鄙視這種抄寫別人博客文章而

不著名轉載出處的人)。於是我就去看源碼能否看到一些好的描述。

Message msg = handler.obtainMessage();
msg.what = xxx;
msg.arg1  = xxx;
msg.arg2  = xxx;
msg.obj    = xxx;

.................... 

看看這兩段代碼其實就是方法不一樣 ,參數都一樣。但是為何實現的效果一樣還要分離出來這么多方法呢?

到源碼去看個究竟吧!

先去看sendMessage()這個方法。。。。它調用的是Handler 中的sendMessage(Message msg)

源碼 片段1  如下:

/**
     * Pushes a message onto the end of the message queue after all pending messages
     * before the current time. It will be received in {@link #handleMessage},
     * in the thread attached to this handler.
     *  
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.
     */
    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

 再看handler.obtainMessage()源碼 片段2 如下:

 /**
     * Returns a new {@link android.os.Message Message} from the global message pool. 
   * More efficient than creating and allocating new instances.
   * The retrieved message has its handler set to this instance    
   * (Message.target == this). * If you don't want that facility, just call Message.obtain() instead. */ public final Message obtainMessage() { return Message.obtain(this); }

  

上面這兩段都是Handler 里面的方法,不過在片段1  我們可以看到Message是我們作為參數傳過去的,片段2的則是我們

Message幫我們處理,它調用obtain(Handler h)方法,之后我們還要調用Message中sendToTarget()這個方法。

看一下Message.obtain(Hanlder h) 的源碼  代碼片段3如下:

  /**
     * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message return   * ed.
     * @param h  Handler to assign to the returned Message object's <em>target</em> member.
     * @return A Message object from the global pool.
     */
    public static Message obtain(Handler h) {
        Message m = obtain();
        m.target = h;

        return m;
    }

  再看 sendToTarget() 源碼     代碼片段4 如下:

  /**
     * Sends this Message to the Handler specified by {@link #getTarget}.
     * Throws a null pointer exception if this field has not been set.
     */
    public void sendToTarget() {
        target.sendMessage(this);
    }

  這里的target就是handler,sendToTarget()又在調用handler的 sendMessage 方法了。。。

     看到這里也許有的人很疑惑,這樣轉來轉去,轉了一圈怎么又回到Handler的 sendMessage方法了?那么性能比較一說

     還有其他的證據么?(難道調用的方法多性能就低么?也許有這么一點原因,不過這里幾乎可以不考慮這一點性能損耗的)

     那么性能的比較證據應該從哪里找呢?

 

  其實細心的同學已經看到了,注意看源碼的注釋,

/**
* Returns a new {@link android.os.Message Message} from the global message pool. More efficient than
* creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).
* If you don't want that facility, just call Message.obtain() instead.
*/

    這里我們的Message 已經不是 自己創建的了,而是從MessagePool 拿的,省去了創建對象申請內存的開銷。。。。。

   到這里大家應該都明白了。所以以后使用的時候盡量使用 Message msg = handler.obtainMessage();的形式創

   建Message,不要自己New Message 至於message產生之后你使用obtainMessage 或者是 sendMessage 效率影響

   並不大.同時我們也要注意以后談論性能的時候要找准位置,譬如這里性能的問題不是在調用 obtainMessage 和 sen

  dMessage 的方法上,而是調用他們之前對象的創建問題上。

  注意:本文嚴謹 轉載 !


免責聲明!

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



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