Message

原文地址:http://blog.csdn.net/wcs542882916

packageandroid.os;

 

importandroid.util.TimeUtils;

 

/**

 *

 *Defines a message containing a description and arbitrary data object that canbe

 *sent to a {@link Handler}.  This object contains two extraintfields and an

 *extra object field that allow you to not do allocations in many cases. 

 *

 *<p class="note">While the constructor of Message is public, thebest way to get

 *one of these is to call {@link#obtain Message.obtain()} or one ofthe

 * {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull

 *them from a pool of recycled objects.</p>

 *

 * 定义一个Message,包含一个描述和一个任意的数据对象,该数据对象能够发送给Handler。

 * 该Message对象包含两个额外的int域和一个额外的Object域,这样就使得你在大多数情况下不用去开辟新的内存。

 *

 * 注意:然而Message的构造方法是public的,但是最好的方法是通过Message.obtain()获取Message对象,

 * 或者通过Handler.obtainMessage()方法获取,

 * 这样是从回收对象池(估计与全局消息池有稍微差别吧)里获取的Message对象,且初始化为初值,大大节省了内存的开销。

 */

public final classMessage implementsParcelable {

    /**

    * User-definedmessage 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.

    *

    * 用户定义的message编号,所以接受者能够识别这个message是干什么的。

    * 每个Handler有它自己的message编号命名空间,也就是说哪个Handler发送的Message就哪个Handler接收,

    * 不用担心与其它Handler之间相互冲突。

    */

    public int what;

 

    /**

    * arg1 and arg2 are lower-cost alternatives to using

    * {@link #setData(Bundle) setData()} if you only need to store a

    * few integer values.

    *

    * arg1和arg2是使用#setData(Bundle)方法的低消耗替代品,如果你只需要使用几个int值。

    */

    public int arg1;

    public int arg2;

 

    /**

    * 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 itcontains aParcelable of a framework class (not one

    * implemented by the application).  For other data transfer use

    * {@link #setData}.

    *

    * <p>Note thatParcelable objects here are not supported prior to

    * the {@linkandroid.os.Build.VERSION_CODES#FROYO} release.

    *

    * 发送给接收者的任意对象。当使用Messenger发送跨进程的message的时候,该域值是否不为null,

    * 要看obj里的对象是否实现了一个框架类的Parcelable(不是应用里自己实现的)。

    * 对于其它的数据传输还可以使用#setData

    */

    public Objectobj;

 

    /**

    * Optional Messenger where replies to this message can be sent.  The

    * semantics of exactly how this is used are up to the sender and

    * receiver.

    */

    //暂时没有用到

    publicMessengerreplyTo;

 

    /**

    * Optional field indicating the uid that sent the message.  This is

    * only valid for messages posted by a{@link Messenger}; otherwise,

    * it will be -1.

    */

    //暂时没有用到

    public int sendingUid = -1;

 

    /** If set message is in use.

    * This flag is set when the message is enqueued and remains set while it

    * is delivered and afterwards when it is recycled.  The flag is only cleared

    * when a new message is created or obtained since that is the only timethat

    * applications are allowed to modify the contents of the message.

    *

    * It is an error to attempt to enqueue or recycle a message that isalready in use.

    */

    /*package*/ staticfinal intFLAG_IN_USE = 1 << 0;

 

    /** If set message is asynchronous */

    /*package*/ staticfinal intFLAG_ASYNCHRONOUS = 1 <<1;

 

    /** Flags to clear in the copyFrom method */

    /*package*/ staticfinal intFLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;

 

    /*package*/ intflags;

 

    /*package*/ longwhen;

   

    /*package*/ Bundle data;

   

    /*package*/ Handler target;

   

    /*package*/ Runnable callback;

   

    // sometimes we store linked lists of these things

    /*package*/ Message next;

 

    /// M: Add message protect mechanism

    /**

    * @hide

    */

    public boolean hasRecycle = false;

 

    private static final Object sPoolSync =new Object();

    private staticMessage sPool;

    private static int sPoolSize= 0;

 

    private static final int MAX_POOL_SIZE = 50;

 

    private static boolean gCheckRecycle=true;

 

    /**

    * Return a new Message instance from the global pool. Allows us to

    * avoid allocating new objects in many cases.

    *

    * 从全局消息池里返回一个新的Message实例。在大多数情况下可以避免开辟新的对象。

    * 全局消息池里默认是50个Message,若是超过了就会直接new一个新的对象。

    */

    public staticMessage obtain() {

       synchronized(sPoolSync) {

           if(sPool !=null) {

                Message m = sPool;

                sPool = m.next;

                m.next = null;

                m.flags = 0; // clear in-use flag

                sPoolSize--;

                /// M: Add message protect mechanism

                m.hasRecycle =false;

                return m;

           }

       }

       return new Message();

    }

 

    /**

    * 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.

    *

    * 和#obtain()一样,但是这个方法是复制已存在的message的值到新的message,包括target值。

    * 返回一个从全局消息池中获得的Message对象,

    * 此时,参数Message的所有数据已被拷贝到这个返回的Message对象里

    */

    public staticMessage 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;

 

       returnm;

    }

 

    /**

    * Same as {@link #obtain()}, but sets the value for the<em>target</em> member on the Message returned.

    * @param h  Handler to assign to thereturned Message object's<em>target</em> member.

    * @return A Message object from the global pool.

    *

    * 和#obtain()方法一样,但是这个方法会在返回message的时候设置这个message的target域值为Handler

    */

    public staticMessage obtain(Handler h) {

       Message m = obtain();

       m.target= h;

 

       returnm;

    }

 

    /**

    * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on

    * the Message that is returned.

    * @param h  Handler to assign to thereturned 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.

    *

    * 这个方法会在返回message的时候设置target域和callback域,这两个域对应的类型是Handler和Runnable。

    * 如果有设置Runnable,那么在发送message后会处理Runnable而不会进入到Handler#handlMessage方法,

    * 这时因为Handler在分发message的时候对于设置Runnable的message对象会优先处理并返回。

    */

    public staticMessage obtain(Handler h, Runnable callback) {

        Message m = obtain();

       m.target= h;

       m.callback= callback;

 

       returnm;

    }

 

    /**

    * 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.

    *

    * 返回message的时候设置了target和what域值

    */

    public staticMessage obtain(Handler h, intwhat) {

       Message m = obtain();

       m.target= h;

       m.what= what;

 

       returnm;

    }

 

    /**

    * 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 globalpool.

    *

    * 返回的时候设置了target、what和obj域。

    */

    public staticMessage obtain(Handler h, intwhat, Object obj) {

       Message m = obtain();

       m.target= h;

       m.what= what;

       m.obj= obj;

 

       returnm;

    }

 

    /**

    * 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 globalpool.

    *

    * 同上

    */

    public staticMessage obtain(Handler h, intwhat,intarg1, intarg2) {

       Message m = obtain();

       m.target= h;

       m.what= what;

       m.arg1= arg1;

       m.arg2= arg2;

 

       returnm;

    }

 

    /**

    * 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 globalpool.

    *

    * 同上

    */

    public staticMessage obtain(Handler h, intwhat,

           intarg1,intarg2, Object obj) {

       Message m = obtain();

       m.target= h;

       m.what= what;

       m.arg1= arg1;

       m.arg2= arg2;

       m.obj= obj;

 

       returnm;

    }

 

    /** @hide */

    public static void updateCheckRecycle(int targetSdkVersion) {

       if(targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) {

           gCheckRecycle=false;

       }

    }

 

    /**

    * Return a Message instance to the global pool.

    * <p>

    * You MUST NOT touch the Message after calling this function because ithas

    * effectively been freed.  It isan error to recycle a message that is currently

    * enqueued or that is in the process of being delivered to a Handler.

    * </p>

     */

    public voidrecycle() {

       if(isInUse()) {

           if(gCheckRecycle){

                throw newIllegalStateException("Thismessage cannot be recycled because it "

                        + "is still in use.");

           }

           return;

       }

       recycleUnchecked();

    }

 

    /**

    * Recycles a Message that may be in-use.

    * Used internally by the MessageQueue and Looper when disposing ofqueued Messages.

    */

    void recycleUnchecked() {

       // Mark the message as in use while itremains in the recycled object pool.

       // Clear out all other details.

       flags= FLAG_IN_USE;

       what= 0;

       arg1= 0;

       arg2= 0;

       obj= null;

       replyTo= null;

       sendingUid= -1;

       when= 0;

       target= null;

       callback= null;

       data= null;

       hasRecycle= true;

       synchronized(sPoolSync) {

           if(sPoolSize <MAX_POOL_SIZE) {

                next = sPool;

                sPool =this;

                sPoolSize++;

           }

       }

    }

 

    /**

    * Make this message like o. Performs a shallow copy of the data field.

    * Does not copy the linked list fields, nor thetimestamp or

    * target/callback of the original message.

    *

    * 跟obtain(Messageorig)方法有所不同,该方法中没有拷贝target和callback域

    */

    public voidcopyFrom(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;

       }

    }

 

    /**

    * Return the targeted delivery time of this message, in milliseconds.

    *

    * 直接返回这个message的定向投放时间,毫秒为单位

    */

    public longgetWhen() {

       returnwhen;

    }

   

    /**

    * 直接设置target

    */

    public voidsetTarget(Handler target) {

       this.target = target;

    }

 

    /**

    * Retrieve the a {@linkandroid.os.Handler Handler}implementation that

    * will receive this message. The object must implement

    * {@linkandroid.os.Handler#handleMessage(android.os.Message)

    * Handler.handleMessage()}. Each Handler has its own name-space for

    * message codes, so you do not need to

    * worry about yours conflicting with other handlers.

    *

    * 直接返回target域值,没有就是初值null

    */

    public Handler getTarget() {

       returntarget;

    }

 

    /**

    * Retrieve callback object that will execute when this message ishandled.

    * This object must implement Runnable. This is called by

    * the <em>target</em>{@link Handler} that is receiving this Message to

    * dispatch it.  If

    * not set, the message will be dispatched to the receiving Handler's

    * {@link Handler#handleMessage(MessageHandler.handleMessage())}.

    *

    * 直接返回callback域值

    */

    public Runnable getCallback() {

       returncallback;

    }

   

    /**

    * Obtains a Bundle of arbitrary data associated with this

    * event, lazily creating it if necessary. Set this value by calling

    * {@link #setData(Bundle)}.  Note that when transferring dataacross

    * processes via {@linkMessenger}, you will need to set your ClassLoader

    * on the Bundle via {@linkBundle#setClassLoader(ClassLoader)

    * Bundle.setClassLoader()} so that it can instantiate your objects when

    * you retrieve them.

    * @see #peekData()

    * @see #setData(Bundle)

    *

    * 返回data(bundle)域值,如果为null则创建一个对象返回

    */

    public Bundle getData() {

       if(data ==null) {

           data= new Bundle();

       }

       

       returndata;

    }

 

    /**

    * Like getData(), but does not lazily create the Bundle.  A null

    * is returned if the Bundle does not already exist.  See

    * {@link #getData} for further information on this.

    * @see #getData()

    * @see #setData(Bundle)

    *

    * 直接返回data(bundle)域值,如果为null就返回null

    */

    public Bundle peekData() {

       returndata;

    }

 

    /**

    * Sets a Bundle of arbitrary data values. Use arg1 and arg2 members

    * as a lower cost way to send a few simple integer values, if you can.

    * @see #getData()

    * @see #peekData()

    *

    * 直接设置data(bundle)域值

    */

    public voidsetData(Bundle data) {

       this.data = data;

    }

 

    /**

    * Sends this Message to the Handler specified by{@link #getTarget}.

    * Throws a null pointer exception if this field has not been set.

    *

    * 发送到target指定的Handler,如果为空则抛出空指针异常

    */

    public voidsendToTarget() {

       target.sendMessage(this);

    }

 

    /**

    * Returns true if the message is asynchronous.

    *

    * Asynchronous messages represent interrupts or events that do notrequire global ordering

    * with represent to synchronous messages.  Asynchronous messages are not subject to

    * the synchronization barriers introduced by{@link MessageQueue#enqueueSyncBarrier(long)}.

    *

    * @return True if the message is asynchronous.

    *

     * @see #setAsynchronous(boolean)

    * @see MessageQueue#enqueueSyncBarrier(long)

    * @see MessageQueue#removeSyncBarrier(int)

    *

    * @hide

    */

    public booleanisAsynchronous() {

       return(flags &FLAG_ASYNCHRONOUS) != 0;

    }

 

    /**

    * Sets whether the message is asynchronous.

    *

    * Asynchronous messages represent interrupts or events that do notrequire global ordering

    * with represent to synchronous messages.  Asynchronous messages are not subject to

    * the synchronization barriers introduced by{@link MessageQueue#enqueueSyncBarrier(long)}.

    *

    * @param async True if the message is asynchronous.

    *

    * @see #isAsynchronous()

    * @see MessageQueue#enqueueSyncBarrier(long)

    * @see MessageQueue#removeSyncBarrier(int)

    *

    * @hide

    */

    public voidsetAsynchronous(booleanasync) {

       if(async) {

           flags|= FLAG_ASYNCHRONOUS;

       } else{

           flags&= ~FLAG_ASYNCHRONOUS;

       }

    }

 

    /*package*/ booleanisInUse() {

       return((flags &FLAG_IN_USE) == FLAG_IN_USE);

    }

 

    /*package*/ voidmarkInUse() {

       flags|= FLAG_IN_USE;

    }

 

    /** Constructor (but the preferred way to get a Message

    *  is to call {@link #obtain() Message.obtain()}).

   */

    //不推荐使用这个构造方法创建message实例,

    //使用Message.obtain()之类的方法创建更节省资源

    public Message() {

    }

 

    @Override

    public String toString() {

       returntoString(SystemClock.uptimeMillis());

    }

 

   String toString(longnow) {

       StringBuilder b = newStringBuilder();

       b.append("{ when=");

       TimeUtils.formatDuration(when - now, b);

 

       if(target !=null) {

           if(callback !=null) {

                b.append(" callback=");

                b.append(callback.getClass().getName());

           } else{

                b.append(" what=");

                b.append(what);

           }

 

           if(arg1 != 0) {

                b.append(" arg1=");

                b.append(arg1);

           }

 

           if(arg2 != 0) {

                b.append(" arg2=");

                b.append(arg2);

           }

 

           if(obj !=null) {

                b.append(" obj=");

                b.append(obj);

           }

 

           b.append(" target=");

           b.append(target.getClass().getName());

       } else{

           b.append(" barrier=");

           b.append(arg1);

       }

       /// M: ALPS00302022

       if(callback !=null) {

           b.append(" callback=");

           b.append(callback);

    }

       if(obj !=null) {

           b.append(" obj=");

           b.append(obj);

    }

       /// M: ALPS00302022

       b.append(" }");

       returnb.toString();

    }

 

    public static final Parcelable.Creator<Message>CREATOR

           = newParcelable.Creator<Message>() {

       publicMessage createFromParcel(Parcel source) {

           Message msg = Message.obtain();

           msg.readFromParcel(source);

            return msg;

       }

       

       publicMessage[] newArray(intsize) {

           return new Message[size];

       }

    };

       

    public intdescribeContents() {

       return0;

    }

 

    public voidwriteToParcel(Parcel dest, intflags) {

       if(callback !=null) {

           throw new RuntimeException(

                "Can't marshal callbacks across processes.");

       }

       dest.writeInt(what);

       dest.writeInt(arg1);

       dest.writeInt(arg2);

       if(obj !=null) {

           try{

                Parcelable p = (Parcelable)obj;

                dest.writeInt(1);

                dest.writeParcelable(p, flags);

           } catch(ClassCastException e) {

                throw newRuntimeException(

                    "Can't marshal non-Parcelable objects across processes.");

           }

       } else{

           dest.writeInt(0);

       }

       dest.writeLong(when);

       dest.writeBundle(data);

       Messenger.writeMessengerOrNullToParcel(replyTo, dest);

       dest.writeInt(sendingUid);

    }

 

    private voidreadFromParcel(Parcel source) {

       what= source.readInt();

       arg1= source.readInt();

       arg2= source.readInt();

       if(source.readInt() != 0) {

           obj= source.readParcelable(getClass().getClassLoader());

       }

       when= source.readLong();

       data= source.readBundle();

       replyTo= Messenger.readMessengerOrNullFromParcel(source);

       sendingUid= source.readInt();

    }

}

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值