原文地址: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();
}
}