Android Handler機(jī)制5之Message簡(jiǎn)介與消息對(duì)象對(duì)象池

Android Handler機(jī)制系列文章整體內(nèi)容如下:

本片文章的主要內(nèi)容下:

  • 1、Message和MessageQueue類注釋
  • 2、獲取Message成員變量解析
  • 3、獲取Message對(duì)象
  • 4、Message的消息對(duì)象池和無(wú)參的obtain()方法
  • 5、obtain()有參函數(shù)解析
  • 6、Message的 淺拷貝

一、 Message和MessageQueue類注釋

為了讓大家更好的理解谷歌團(tuán)隊(duì)設(shè)計(jì)這個(gè)兩個(gè)類Message和MessageQueue的意圖,我們還是從這個(gè)兩個(gè)類的類注釋開始

(一) Message.java

Message

Defines a message containing a description and arbitrary data object that can be sent to a Handler. This object contains two extra int fields and an extra object field that allow you to not do allocations in many cases.
While the constructor of Message is public, the best way to get one of these is to call Message.obtain() or one of the Handler.obtainMessage() methods, which will pull them from a pool of recycled objects.

翻譯一下:

定義一個(gè)可以發(fā)送給Handler的描述和任意數(shù)據(jù)對(duì)象的消息。此對(duì)象包含兩個(gè)額外的int字段和一個(gè)額外的對(duì)象字段,這樣就可以使用在很多情況下不用做分配工作。
盡管Message的構(gòu)造器是公開的,但是獲取Message對(duì)象的最好方法是調(diào)用Message.obtain()或者Handler.obtainMessage(),這樣是從一個(gè)可回收的對(duì)象池中獲取Message對(duì)象。

至此Java層面Handler機(jī)制中最重要的四個(gè)類大家有了一個(gè)初步印象。下面咱們?cè)创a跟蹤一下

二、獲取Message成員變量解析

(一) 成員變量 what

Message用一個(gè)標(biāo)志來(lái)區(qū)分不同消息的身份,不同的Handler使用相同的消息不會(huì)弄混,一般使用16進(jìn)制形式來(lái)表示,閱讀起來(lái)比較容易

代碼在Message.java 39行

    /**
     * User-defined message code so that the recipient can identify 
     * what this message is about. Each {@link Handler} has its own name-space
     * for message codes, so you do not need to worry about yours conflicting
     * with other handlers.
     */
    public int what;

注釋翻譯:

用戶定義的Message的標(biāo)識(shí)符用以分辨消息的內(nèi)容。Hander擁有自己的消息代碼的命名空間,因此你不用擔(dān)心與其他的Handler沖突。

(二) 成員變量 arg1和arg2

arg1和arg2都是Message類的可選變量,可以用來(lái)存放兩個(gè)整數(shù)值,不用訪問(wèn)obj對(duì)象就能讀取的變量。

代碼在Message.java 46行

    /**
     * arg1 and arg2 are lower-cost alternatives to using
     * {@link #setData(Bundle) setData()} if you only need to store a
     * few integer values.
     */
    public int arg1; 

    /**
     * arg1 and arg2 are lower-cost alternatives to using
     * {@link #setData(Bundle) setData()} if you only need to store a
     * few integer values.
     */
    public int arg2;

因?yàn)閮蓚€(gè)注釋一樣,我就不重復(fù)翻譯了,翻譯如下:

如果你僅僅是保存幾個(gè)整形的數(shù)值,相對(duì)于使用setData()方法,使用arg1和arg2是較低成本的替代方案。

(三) 成員變量 obj

obj 用來(lái)保存對(duì)象,接受纖細(xì)后取出獲得傳送的對(duì)象。

代碼在Message.java 65行

    /**
     * An arbitrary object to send to the recipient.  When using
     * {@link Messenger} to send the message across processes this can only
     * be non-null if it contains a Parcelable of a framework class (not one
     * implemented by the application).   For other data transfer use
     * {@link #setData}.
     * 
     * <p>Note that Parcelable objects here are not supported prior to
     * the {@link android.os.Build.VERSION_CODES#FROYO} release.
     */
    public Object obj;

注釋翻譯:

  • 將一個(gè)獨(dú)立的對(duì)象發(fā)送給接收者。當(dāng)使用Messenger去送法消息,并且這個(gè)對(duì)象包含Parcelable類的時(shí)候,它必須是非空的。對(duì)于其他數(shù)據(jù)的傳輸,建議使用setData()方法
  • 請(qǐng)注意,在Android系統(tǒng)版本FROYO(2.2)之前不支持Parcelable對(duì)象。

(四) 其他成員變量

其他變量我就不一一解釋了,大家就直接看注釋吧

    // 回復(fù)跨進(jìn)程的Messenger 
    public Messenger replyTo;

    // Messager發(fā)送這的Uid
    public int sendingUid = -1;

    // 正在使用的標(biāo)志值 表示當(dāng)前Message 正處于使用狀態(tài),當(dāng)Message處于消息隊(duì)列中、處于消息池中或者Handler正在處理Message的時(shí)候,它就處于使用狀態(tài)。
    /*package*/ static final int FLAG_IN_USE = 1 << 0;

    // 異步標(biāo)志值 表示當(dāng)前Message是異步的。
    /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;

    // 消息標(biāo)志值 在調(diào)用copyFrom()方法時(shí),該常量將會(huì)被設(shè)置,其值其實(shí)和FLAG_IN_USE一樣
    /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;

    // 消息標(biāo)志,上面三個(gè)常量 FLAG 用在這里
    /*package*/ int flags;

    // 用于存儲(chǔ)發(fā)送消息的時(shí)間點(diǎn),以毫秒為單位
    /*package*/ long when;

    // 用于存儲(chǔ)比較復(fù)雜的數(shù)據(jù)
    /*package*/ Bundle data;
    
    // 用于存儲(chǔ)發(fā)送當(dāng)前Message的Handler對(duì)象,前面提到過(guò)Handler其實(shí)和Message相互持有引用的
    /*package*/ Handler target;
    
    // 用于存儲(chǔ)將會(huì)執(zhí)行的Runnable對(duì)象,前面提到過(guò)除了handlerMessage(Message msg)方法,你也可以使用Runnable執(zhí)行操作,要注意的是這種方法并不會(huì)創(chuàng)建新的線程。
    /*package*/ Runnable callback;
 
    // 指向下一個(gè)Message,也就是線程池其實(shí)是一個(gè)鏈表結(jié)構(gòu)
    /*package*/ Message next;

    // 該靜態(tài)變量?jī)H僅是為了給同步塊提供一個(gè)鎖而已
    private static final Object sPoolSync = new Object();

    //該靜態(tài)的Message是整個(gè)線程池鏈表的頭部,通過(guò)它才能夠逐個(gè)取出對(duì)象池的Message
    private static Message sPool;

    // 該靜態(tài)變量用于記錄對(duì)象池中的Message的數(shù)量,也就是鏈表的長(zhǎng)度
    private static int sPoolSize = 0;
  
    // 設(shè)置了對(duì)象池中的Message的最大數(shù)量,也就是鏈表的最大長(zhǎng)度
    private static final int MAX_POOL_SIZE = 50;

     //該版本系統(tǒng)是否支持回收標(biāo)志位
    private static boolean gCheckRecycle = true;

三、獲取Message對(duì)象

(一)、Message構(gòu)造函數(shù)

如果想獲取Message對(duì)象,大家第一印象肯定是找Message的構(gòu)造函數(shù),那我們就來(lái)看下Message的構(gòu)造函數(shù)。代碼在Message.java 475行

    /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
    */
    public Message() {
    }

發(fā)現(xiàn)代碼里面什么都沒(méi)有

那我們看下注釋,簡(jiǎn)單翻譯一下:

構(gòu)造函數(shù),但是獲取Message的首選方法是通過(guò)Message.obtain()來(lái)調(diào)用

其實(shí)在上面解釋Message的注釋時(shí)也是這樣說(shuō)的,說(shuō)明Android官方團(tuán)隊(duì)是推薦使用Message.obtain()方法來(lái)獲取Message對(duì)象的,那我們就來(lái)看下Message.obtain()

(二)、Message.obtain()方法

我們來(lái)看下Message.java 類的結(jié)構(gòu)圖

Message結(jié)構(gòu)圖.png

Message.居然有8個(gè)obtain函數(shù)
為了方便后續(xù)的跟蹤,也將這8個(gè)方法編號(hào),分別如下

  • ① public static Message obtain()
  • ② public static Message obtain(Message orig)
  • ③ public static Message obtain(Handler h)
  • ④ public static Message obtain(Handler h, Runnable callback)
  • ⑤ public static Message obtain(Handler h, int what)
  • ⑥ public static Message obtain(Handler h, int what, Object obj)
  • ⑦ public static Message obtain(Handler h, int what, int arg1, int arg2)
  • ⑧ public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj)

這里我們也像Handler一樣,分為兩大類

  • 無(wú)參的obtain()方法
  • 有參的obtain()方法

在講解無(wú)參的obtain()的時(shí)候很有必要先了會(huì)涉及一個(gè)概念“Message對(duì)象池”,所以我們就合并一起講解了

四、Message的消息對(duì)象池和無(wú)參的obtain()方法

先來(lái)看一下下面 無(wú)參的obtain()方法的代碼

1、① public static Message obtain(Message orig)

代碼在Message.java 122行

    /**
     * Return a new Message instance from the global pool. Allows us to
     * avoid allocating new objects in many cases.
     */
    public static Message obtain() {
       // 保證線程安全
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                 // flags為移除使用標(biāo)志
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

老規(guī)矩,先看下注釋,翻譯如下:

從全局的pool返回一個(gè)實(shí)例化的Message對(duì)象。這樣可以避免我們重新創(chuàng)建冗余的對(duì)象。

等等上面提到了一個(gè)名詞pool,我們通常理解為"池",我們看到源代碼的里面有一個(gè)變量是"sPool",那么"sPool",這里面就涉及到了Message的設(shè)計(jì)原理了,在Message里面是有一個(gè)"對(duì)象池",下面我們就詳細(xì)了解下

2、sPool

代碼在Message.java 111行

   private static Message sPool;
  • 好像也沒(méi)什么嘛?就是一個(gè)Message對(duì)象而已,所以sPool默認(rèn)是null。
  • 這時(shí)候我們?cè)賮?lái)看上面public static Message obtain()方法,我們發(fā)現(xiàn)public static Message obtain()就是直接new了Message 直接返回而已。好像很簡(jiǎn)單的樣子,大家心里肯定感覺(jué)"咱們是不是忽略了什么?"
  • 是的,既然官方是不推薦使用new Message的,因?yàn)檫@樣可能會(huì)重新創(chuàng)建冗余的對(duì)象。所以我們推測(cè)大部分情況下sPool是不為null的。那我們就反過(guò)來(lái)看下,來(lái)全局找下sPool什么時(shí)候被賦值的

我們發(fā)現(xiàn)除了public static Message obtain()里面的if (sPool != null) {}里面外,還有recycleUnchecked給sPool賦值了。那我們就來(lái)看下這個(gè)方法

3、recycleUnchecked()

代碼在Message.java 291行

   /**
     * Recycles a Message that may be in-use.
     * Used internally by the MessageQueue and Looper when disposing of queued Messages.
     */
    void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        // 添加正在使用標(biāo)志位,其他情況就除掉
        flags = FLAG_IN_USE;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        sendingUid = -1;
        when = 0;
        target = null;
        callback = null;
        data = null;
        //拿到同步鎖,以避免線程不安全
        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }
4、消息對(duì)象池的理解

為了讓大家更好的理解,我把recycleUnchecked()和obtain()合在一起,省略一些不重要的代碼
代碼如下:

void recycleUnchecked() {
                ...
        if (sPoolSize < MAX_POOL_SIZE) {
                // 第一步
                next = sPool;
                 // 第二步
                sPool = this;
                 // 第三步
                sPoolSize++;
                 ...
         }
    }

public static Message obtain() {
    synchronized (sPoolSync) {
        //第一步
        if (sPool != null) {
            // 第二步
            Message m = sPool;
            // 第三步
            sPool = m.next;
            // 第四步
            m.next = null;
            // 第五步
            m.flags = 0; 
            // 第六步
            sPoolSize--;
            return m;
        }
    }
}
4.1、recycleUnchecked()的理解

假設(shè)消息對(duì)象池為空,從new message開始,到這個(gè)message被取出使用后,準(zhǔn)備回收 先來(lái)看recycleUnchecked()方法

  • 第一步,next=sPool,因?yàn)橄?duì)象池為空,所以此時(shí)sPool為null,同時(shí)next也為null。
  • 第二步,spool = this,將當(dāng)前這個(gè)message作為消息對(duì)象池中下一個(gè)被復(fù)用的對(duì)象。
  • 第三步,sPoolSize++,默認(rèn)為0,此時(shí)為1,將消息對(duì)象池的數(shù)量+1,這個(gè)數(shù)量依然是全系統(tǒng)共共享的。

這時(shí)候假設(shè)又調(diào)用了,這個(gè)方法,之前的原來(lái)的第一個(gè)Message對(duì)象我假設(shè)定位以為message1,依舊走到上面的循環(huán)。

  • 第一步,next=sPool,因?yàn)橄?duì)象池為message1,所以此時(shí)sPool為message1,同時(shí)next也為message1。
  • 第二步,sPool = this,將當(dāng)前這個(gè)message作為消息對(duì)象池中下一個(gè)被復(fù)用的對(duì)象。
  • 第三步,sPoolSize++,此時(shí)為1,將消息對(duì)象池的數(shù)量+1,sPoolSize為2,這個(gè)數(shù)量依然是全系統(tǒng)共共享的。

以此類推,直到sPoolSize=50(MAX_POOL_SIZE = 50)

4.2、obtain()的理解

假設(shè)上面已經(jīng)回收了一個(gè)Message對(duì)象,又從這里獲取一個(gè)message,看看會(huì)發(fā)生什么?

  • 第一步,判斷sPool是否為空,如果消息對(duì)象池為空,則直接new Message并返回
  • 第二步,Message m = sPool,將消息對(duì)象池中的對(duì)象取出來(lái),為m。
  • 第三步,sPool = m.next,將消息對(duì)象池中的下一個(gè)可以復(fù)用的Message對(duì)象(m.next)賦值為消息對(duì)象池中的當(dāng)前對(duì)象。(如果消息對(duì)象池就之前就一個(gè),則此時(shí)sPool=null)
  • 第四步,將m.next置為null,因?yàn)橹耙呀?jīng)把這個(gè)對(duì)象取出來(lái)了,所以無(wú)所謂了。
  • 第五步,m.flags = 0,設(shè)置m的標(biāo)記位,標(biāo)記位正在被使用
  • 第六步,sPoolSize--,因?yàn)橐呀?jīng)把m取出了,這時(shí)候要把消息對(duì)象池的容量減一。
4.3、深入理解消息對(duì)象池

上面的過(guò)程主要討論只有一個(gè)message的情況,詳細(xì)解釋一下sPool和next,將sPool看成一個(gè)指針,通過(guò)next來(lái)將對(duì)象組成一個(gè)鏈表,因?yàn)槊看沃恍枰獜某刈永锬贸鲆粋€(gè)對(duì)象,所以不需要關(guān)心池子里具體有多少個(gè)對(duì)象,而是拿出當(dāng)前這個(gè)sPool所指向的這個(gè)對(duì)象就可以了,sPool從思路上理解就是通過(guò)左右移動(dòng)來(lái)完成復(fù)用和回收

4.3.1、obtain()復(fù)用

如下圖:


obtain()復(fù)用1.png

當(dāng)移動(dòng)Obtain()的時(shí)候,讓sPool=next,因此第一個(gè)message.next就等于第二個(gè)message,從上圖看相當(dāng)于指針向后移動(dòng)了一位,隨后會(huì)將第一個(gè)message.next的值置為空。如下圖:

obtain()復(fù)用2.png

現(xiàn)在這個(gè)鏈表看上去就斷了,如果in-use這個(gè)message使用完畢了,怎么回到鏈表中?這就是recycleUnchecked() – 回收了

4.3.2、recycleUnchecked()回收

這時(shí)候在看下recycleUnchecked()里面的代碼,next = sPool,將當(dāng)前sPool所指向的message對(duì)象賦值給in-use的next,然后sPool=this,將sPool指向第一個(gè)message對(duì)象。如下圖:

ecycleUnchecked()回收.png

這樣,就將鏈表恢復(fù)了,而且不管是復(fù)用還是回收大歐式保證線程同步的,所以始終會(huì)形成一條鏈?zhǔn)浇Y(jié)構(gòu)。

如下圖

回收.png

五、obtain()有參函數(shù)解析

(一)、② public static Message obtain(Message orig)

代碼在Message.java 142行

   /**
     * Same as {@link #obtain()}, but copies the values of an existing
     * message (including its target) into the new one.
     * @param orig Original message to copy.
     * @return A Message object from the global pool.
     */
    public static Message obtain(Message orig) {
        Message m = obtain();
        m.what = orig.what;
        m.arg1 = orig.arg1;
        m.arg2 = orig.arg2;
        m.obj = orig.obj;
        m.replyTo = orig.replyTo;
        m.sendingUid = orig.sendingUid;
        if (orig.data != null) {
            m.data = new Bundle(orig.data);
        }
        m.target = orig.target;
        m.callback = orig.callback;

        return m;
    }

先翻譯注釋:

和obtain()一樣,但是將message的所有內(nèi)容復(fù)制一份到新的消息中。

看代碼我們知道首先調(diào)用obtain()從消息對(duì)象池中獲取一個(gè)Message對(duì)象m,然后把orig中的所有屬性賦值給m。

(二)、③ public static Message obtain(Handler h)

代碼在Message.java 164行

     /**
     * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.
     * @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;
    }

先翻譯注釋:

和obtain()一樣,但是成員變量中的target的值用以指定的值(入?yún)?來(lái)替換。

代碼很簡(jiǎn)單就是調(diào)用obtain()從消息對(duì)象池中獲取一個(gè)Message對(duì)象m,然后將m的target重新賦值而已。

(三)、④ public static Message obtain(Handler h, Runnable callback)

代碼在Message.java 178行

    /**
     * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on
     * the Message that is returned.
     * @param h  Handler to assign to the returned Message object's <em>target</em> member.
     * @param callback Runnable that will execute when the message is handled.
     * @return A Message object from the global pool.
     */
    public static Message obtain(Handler h, Runnable callback) {
        Message m = obtain();
        m.target = h;
        m.callback = callback;

        return m;
    }

先翻譯注釋:

和obtain()一樣,但是成員變量中的target的值用以指定的值(入?yún)?來(lái)替換,并且添加一個(gè)回調(diào)的Runnable

代碼很簡(jiǎn)單就是調(diào)用obtain()從消息對(duì)象池中獲取一個(gè)Message對(duì)象m,然后將m的target和m的callback重新賦值而已。

(四)、⑤ public static Message obtain(Handler h, int what)

代碼在Message.java 193行

    /**
     * Same as {@link #obtain()}, but sets the values for both <em>target</em> and
     * <em>what</em> members on the Message.
     * @param h  Value to assign to the <em>target</em> member.
     * @param what  Value to assign to the <em>what</em> member.
     * @return A Message object from the global pool.
     */
    public static Message obtain(Handler h, int what) {
        Message m = obtain();
        m.target = h;
        m.what = what;

        return m;
    }

先翻譯注釋:

和obtain()一樣,但是重置了成員變量target和what的值。

代碼很簡(jiǎn)單就是調(diào)用obtain()從消息對(duì)象池中獲取一個(gè)Message對(duì)象m,然后將m的target和m的what重新賦值而已。

(五)、public static Message obtain(Handler h, int what, Object obj)

代碼在Message.java 209行

    /**
     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em>
     * members.
     * @param h  The <em>target</em> value to set.
     * @param what  The <em>what</em> value to set.
     * @param obj  The <em>object</em> method to set.
     * @return  A Message object from the global pool.
     */
    public static Message obtain(Handler h, int what, Object obj) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.obj = obj;

        return m;
    }

先翻譯注釋:

和obtain()一樣,但是重置了成員變量target、what、obj的值。

代碼很簡(jiǎn)單就是調(diào)用obtain()從消息對(duì)象池中獲取一個(gè)Message對(duì)象m,然后將m的target、what和obj這三個(gè)成員變量重新賦值而已。

(六)、⑦ public static Message obtain(Handler h, int what, int arg1, int arg2)

代碼在Message.java 228行

    /**
     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, 
     * <em>arg1</em>, and <em>arg2</em> members.
     * 
     * @param h  The <em>target</em> value to set.
     * @param what  The <em>what</em> value to set.
     * @param arg1  The <em>arg1</em> value to set.
     * @param arg2  The <em>arg2</em> value to set.
     * @return  A Message object from the global pool.
     */
    public static Message obtain(Handler h, int what, int arg1, int arg2) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.arg1 = arg1;
        m.arg2 = arg2;

        return m;
    }

先翻譯注釋:

和obtain()一樣,但是重置了成員變量target、what、arg1、arg2的值。

代碼很簡(jiǎn)單就是調(diào)用obtain()從消息對(duì)象池中獲取一個(gè)Message對(duì)象m,然后將m的target、what、arg1、arg2這四個(gè)成員變量重新賦值而已。

(七)、⑧ public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj)

代碼在Message.java 249行

    /**
     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, 
     * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members.
     * 
     * @param h  The <em>target</em> value to set.
     * @param what  The <em>what</em> value to set.
     * @param arg1  The <em>arg1</em> value to set.
     * @param arg2  The <em>arg2</em> value to set.
     * @param obj  The <em>obj</em> value to set.
     * @return  A Message object from the global pool.
     */
    public static Message obtain(Handler h, int what, 
            int arg1, int arg2, Object obj) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.arg1 = arg1;
        m.arg2 = arg2;
        m.obj = obj;

        return m;
    }

先翻譯注釋:

和obtain()一樣,但是重置了成員變量target、what、arg1、arg2、obj的值。

代碼很簡(jiǎn)單就是調(diào)用obtain()從消息對(duì)象池中獲取一個(gè)Message對(duì)象m,然后將m的target、what、arg1、arg2、obj這五個(gè)成員變量重新賦值而已。

(八)、總結(jié)

我們發(fā)現(xiàn) 上面有參的obtain()方法里面第一行代碼都是 Message m = obtain();,所以有參的obtain()的方法的本質(zhì)都是調(diào)用無(wú)參的obtain()方法,只不過(guò)有參的obtain()可以通過(guò)入?yún)?lái)重置一些成員變量的值而已

六、Message的 淺拷貝

Message的淺拷貝 就是copyFrom(Message o)函數(shù)
代碼在Message.java 320行

    /**
     * Make this message like o.  Performs a shallow copy of the data field.
     * Does not copy the linked list fields, nor the timestamp or
     * target/callback of the original message.
     */
    public void copyFrom(Message o) {
        this.flags = o.flags & ~FLAGS_TO_CLEAR_ON_COPY_FROM;
        this.what = o.what;
        this.arg1 = o.arg1;
        this.arg2 = o.arg2;
        this.obj = o.obj;
        this.replyTo = o.replyTo;
        this.sendingUid = o.sendingUid;

        if (o.data != null) {
            this.data = (Bundle) o.data.clone();
        } else {
            this.data = null;
        }
    }

先翻譯注釋:

把這個(gè)Message做成像o一樣。執(zhí)行數(shù)據(jù)字段的淺拷貝,不復(fù)制字段連接,也不賦值目標(biāo)的Handler和callback回調(diào)。

其實(shí)從本質(zhì)上看就是從一個(gè)消息體復(fù)制到另一個(gè)消息體。有時(shí)候你可能需要用到Message的拷貝功能,也就是說(shuō)拷貝一個(gè)和Message 一模一樣的B,這時(shí)候你可以使用copyFrom(Message o) 拷貝一個(gè)Message對(duì)象。

有時(shí)候你可能需要用到Message的拷貝功能,也就是說(shuō)拷貝一個(gè)和Message A一模一樣的B,這時(shí)候你可以使用copyFrom(Message o)方法來(lái)淺拷貝一個(gè)Message對(duì)象。從代碼中可以看出大部分?jǐn)?shù)據(jù)確實(shí)都是淺拷貝,但是對(duì)于data這個(gè)Bundle類型的成員變量卻進(jìn)行了深拷貝,所以說(shuō)該方法是一個(gè)淺拷貝方法感覺(jué)也不是很貼切。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容