看下类定义:
- 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.
定义一个包含任意类型的描述数据对象,此对象可以发送给Handler。对象包含两个额外的int字段和一个额外的对象字段,这样可以使得在很多情况下不用做分配工作。尽管Message的构造器是公开的,但是获取Message对象的最好方法是调用Message.obtain()或者Handler.obtainMessage(), 这样是从一个可回收对象池中获取Message对象。
- public final class Message implements Parcelable
Message类是个final类,就是说不能被继承,同时Message类实现了Parcelable接口,我们知道android提供了一种新的类型:Parcel。本类被用作封装数据的容器,封装后的数据可以通过Intent或IPC传递。 除了基本类型以外,只有实现了Parcelable接口的类才能被放入Parcel中。
看一下全局变量:
- /**
- * 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;
- /**
- * 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;
- /**
- * 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;
- /**
- * 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.
- */
- public Messenger replyTo;
- /** If set message is in use */
- /*package*/ static final int FLAG_IN_USE = 1;
- /** Flags reserved for future use (All are reserved for now) */
- /*package*/ static final int FLAGS_RESERVED = ~FLAG_IN_USE;
- /** Flags to clear in the copyFrom method */
- /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAGS_RESERVED | FLAG_IN_USE;
- /*package*/ int flags;
- /*package*/ long when;
- /*package*/ Bundle data;
- /*package*/ Handler target;
- /*package*/ Runnable callback;
- // sometimes we store linked lists of these things
- /*package*/ Message next;
- private static final Object sPoolSync = new Object();
- private static Message sPool;
- private static int sPoolSize = 0;
- private static final int MAX_POOL_SIZE = 10;
- what:用户定义消息代码以便收件人可以识别这是哪一个Message。每个Handler用它自己的名称空间为消息代码,所以您不需要担心你的Handler与其他handler冲突。
- arg1、arg2:如果只是想向message内放一些整数值,可以使用arg1和arg2来代替setData方法。
- obj:发送给接收器的任意对象。当使用Message对象在线程间传递消息时,如果它包含一个Parcelable的结构类(不是由应用程序实现的类),此字段必须为非空(non-null)。其他的数据传输则使用setData(Bundle)方法。注意Parcelable对象是从FROYO版本以后才开始支持的。
- replyTo:指明此message发送到何处的可选Messenger对象。具体的使用方法由发送者和接受者决定。
- FLAG_IN_USE:判断Message是否在使用( default 包内可见)
- FLAGS_RESERVED:留个将来使用??
- FLAGS_TO_CLEAR_ON_COPY_FROM:明确在copyFrom方法
- 其他参数都比较简单,不详述
下面看obtain方法:
- /**
- * 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;
- sPoolSize--;
- return m;
- }
- }
- return new Message();
- }
从全局池中返回一个新的Message实例。在大多数情况下这样可以避免分配新的对象。
在看它一系列的重载方法:
- /**
- * 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;
- }
- /**
- * 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;
- }
- /**
- * 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;
- }
- /**
- * 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;
- }
- /**
- * 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()方法,然后把获取的Message实例加上各种参数。
- /**
- * Return a Message instance to the global pool. You MUST NOT touch
- * the Message after calling this function -- it has effectively been
- * freed.
- */
- public void recycle() {
- clearForRecycle();
- synchronized (sPoolSync) {
- if (sPoolSize < MAX_POOL_SIZE) {
- next = sPool;
- sPool = this;
- sPoolSize++;
- }
- }
- }
向全局池中返回一个Message实例。一定不能在调用此函数后再使用Message——它会立即被释放。
- /**
- * 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;
- if (o.data != null) {
- this.data = (Bundle) o.data.clone();
- } else {
- this.data = null;
- }
- }
使此message跟参数o相似。浅拷贝数据域。不拷贝源message的链表字段,时间戳和目标/回调。
- /**
- * Return the targeted delivery time of this message, in milliseconds.
- */
- public long getWhen() {
- return when;
- }
设置一个任意数据值的Bundle对象。如果可以,使用arg1和arg2域发送一些整型值以减少消耗。
参考
getData()
peekData()
返回此消息的传输时间,以毫秒为单位。
- public void setTarget(Handler target) {
- this.target = target;
- }
设置目标handler(接收其消息的Handler)。
- /**
- * Retrieve the a {@link android.os.Handler Handler} implementation that
- * will receive this message. The object must implement
- * {@link android.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.
- */
- public Handler getTarget() {
- return target;
- }
获取将接收此消息的Handler对象。此对象必须要实现Handler.handleMessage()方法。每个handler各自包含自己的消息代码,所以不用担心自定义的消息跟其他handlers有冲突。
- /**
- * Retrieve callback object that will execute when this message is handled.
- * 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(Message Handler.handleMessage())}.
- */
- public Runnable getCallback() {
- return callback;
- }
获取回调对象,此对象会在message处理时执行。此对象必须实现Runnable接口。回调由接收此消息并分发的目标handler调用。如果没有设置回调,此消息会分发到接收handler的handleMessage(Message)。
- /**
- * 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 data across
- * processes via {@link Messenger}, you will need to set your ClassLoader
- * on the Bundle via {@link Bundle#setClassLoader(ClassLoader)
- * Bundle.setClassLoader()} so that it can instantiate your objects when
- * you retrieve them.
- * @see #peekData()
- * @see #setData(Bundle)
- */
- public Bundle getData() {
- if (data == null) {
- data = new Bundle();
- }
- return data;
- }
获取附加在此事件上的任意数据的Bundle对象,需要时延迟创建。通过调用setData(Bundle)来设置Bundle的值。需要注意的是,如果通过Messenger对象在进程间传递数据时,需要调用Bundle类的Bundle.setClassLoader()方法来设置ClassLoader,这样当接收到消息时可以实例化Bundle里的对象。
参考
peekData()
setData(Bundle)
- /**
- * 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)
- */
- public Bundle peekData() {
- return data;
- }
与getData()相似,但是并不延迟创建Bundle。如果Bundle对象不存在返回null。更多信息见getData()。
参考
getData()
setData(Bundle)
- /**
- * Sets a Bundle of arbitrary data values. Use arg1 and arg1 members
- * as a lower cost way to send a few simple integer values, if you can.
- * @see #getData()
- * @see #peekData()
- */
- public void setData(Bundle data) {
- this.data = data;
- }
设置一个任意数据值的Bundle对象。如果可以,使用arg1和arg2域发送一些整型值以减少消耗。
参考
getData()
peekData()
- /**
- * 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);
- }
向Handler发送此消息,getTarget()方法可以获取此Handler。如果这个字段没有设置会抛出个空指针异常。
- void clearForRecycle() {
- flags = 0;
- what = 0;
- arg1 = 0;
- arg2 = 0;
- obj = null;
- replyTo = null;
- when = 0;
- target = null;
- callback = null;
- data = null;
- }
default方法,包内可见,清空所有数据。
- /*package*/ boolean isInUse() {
- return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
- }
- /*package*/ void markInUse() {
- flags |= FLAG_IN_USE;
- }
获取Message是否在使用和标记为使用。
构造方法:
- /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
- */
- public Message() {
- }
跟推荐使用Message.obtain()方法。
toString方法:
- public String toString() {
- return toString(SystemClock.uptimeMillis());
- }
- String toString(long now) {
- StringBuilder b = new StringBuilder();
- b.append("{ what=");
- b.append(what);
- b.append(" when=");
- TimeUtils.formatDuration(when-now, b);
- 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(" }");
- return b.toString();
- }
- public static final Parcelable.Creator<Message> CREATOR
- = new Parcelable.Creator<Message>() {
- public Message createFromParcel(Parcel source) {
- Message msg = Message.obtain();
- msg.readFromParcel(source);
- return msg;
- }
- public Message[] newArray(int size) {
- return new Message[size];
- }
- };
什么作用?
- public int describeContents() {
- return 0;
- }
描述了包含在Parcelable对象排列信息中的特殊对象的类型。
返回值
一个标志位,表明Parcelable对象特殊对象类型集合的排列。
- public void writeToParcel(Parcel dest, int flags) {
- 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 new RuntimeException(
- "Can't marshal non-Parcelable objects across processes.");
- }
- } else {
- dest.writeInt(0);
- }
- dest.writeLong(when);
- dest.writeBundle(data);
- Messenger.writeMessengerOrNullToParcel(replyTo, dest);
- }
- private final void readFromParcel(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);
- }
将类的数据写入外部提供的Parcel中和从Parcel中读取数据。
相关推荐
《Sinch Android RTC 3.12.3 源码深度解析》 Sinch Android RTC 3.12.3 是一个强大的实时通信库,专为Android平台设计,提供了丰富的功能,包括语音通话、视频通话以及即时消息传递。这款开源源码对于Android开发者...
《ASMACK源码解析——基于Android 19的0.8.10版本》 ASMACK,全称为Asynchronous Smack,是Smack库的扩展,专为Android平台设计,用于处理XMPP(Extensible Messaging and Presence Protocol)协议。XMPP是一种基于...
### Android源码解析知识点概述 #### 公共技术点概览 - **Java反射** - Java反射机制允许运行时检查类、接口、字段和方法的信息,并能够动态地调用方法和修改字段值。 - **应用场景**:动态加载类、实现插件化...
《深入剖析Android应用源码LumaQQ:QQ代码解析》 在移动开发领域,Android以其开源性和灵活性成为了开发者们的首选平台。本篇文章将对“LumaQQ-qq代码.zip”这个压缩包中的Android应用源码进行深度分析,帮助读者...
Android AsyncTask 完全解析,带你从源码的角度彻底理解 Android 异步消息处理机制完全解析,带你从源码角度彻底理解 Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系 Android消息...
《Android源码设计模式解析与实战》是一本深入探讨Android系统源码中设计模式应用的专业书籍,适合希望提升技术能力、研究源码或学习设计模式的开发者。这本书以清晰的结构和实例,揭示了Android系统背后的软件工程...
3. **UI绘制与布局优化**:Android视图系统(View和ViewGroup)的源码解析能帮助我们理解UI渲染过程,从而进行性能优化。例如,如何自定义View,减少无效的测量和绘制,以及如何利用硬件加速来提升性能。 4. **线程...
本文将深入解析这三者的源码,帮助你理解它们的工作原理,并教你如何手写一套自己的Handler系统。 首先,我们来了解Handler。Handler是Android中的一个关键类,用于发送和处理消息。在主线程中,一个Handler对象...
在安卓开发领域,掌握Android源码对于提升技能和理解系统底层运作至关重要,特别是在面试环节,对源码的理解往往能体现一个开发者的深度。本资料"安卓Android源码——面试题-"将聚焦于Android源码相关的面试问题,...
在本项目中,我们主要探讨的是如何在Android平台上...以上就是"Android即时通讯--仿QQ即时聊天源码(含服务器)"项目所涵盖的主要技术点,通过这个项目,开发者可以全面了解即时通讯应用的开发流程,并提升相关技能。
**Android MQTT 源码解析** 在移动应用开发中,实时通信是不可或缺的一部分,而 MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅消息协议,广泛用于物联网(IoT)设备和应用程序之间的低带宽、...
"安卓Android源码——pushMessage.zip" 提供的源码可能是一个简单的推送消息实现,或者是一个完整的推送服务框架。这里我们将围绕Android推送消息的实现、工作原理以及相关技术进行详细讲解。 1. **Android推送消息...
本文将深入解析`ApiDemos`中的一个特定示例——`App->Notification->IncomingMessage`,帮助开发者更好地理解和应用Android的通知功能。 通知(Notification)是Android系统中一种关键的用户界面元素,它在状态栏中...
本文将深入解析Android API的基础内容,帮助新手快速理解并掌握API的使用。 一、Android API概述 Android API是由Java语言编写的,基于Linux内核的开放源码平台。它包含了众多库、服务和工具,为开发者提供了全面...
这个压缩包“安卓Android源码——PushMessage百度的.zip”很可能是包含了实现百度推送服务(Baidu Push)的源代码。在这里,我们将深入探讨如何理解和使用这样的源代码,以及相关的Android推送技术。 首先,我们...
在Android系统中,设计模式是开发者理解和驾驭代码的关键。这些模式源自《设计模式:可复用面向对象软件的基础》一书,由...阅读《Android源码设计模式解析与实战.pdf》这样的资料,将有助于你深入学习和实践这些知识。
本资源"安卓Android源码——android访问网络返回json解析和Hanlder的使用.zip"聚焦于两个核心概念:网络请求与数据解析,以及Handler的使用。我们将深入探讨这两个方面。 首先,Android中的网络访问是应用程序与...
该压缩包文件“Android高级应用源码-仿微信聊天软件,Socket实现.rar”提供了一个学习Android高级应用开发的实例,具体是仿照微信聊天软件的实现。通过使用Socket编程,这个项目展示了如何在Android平台上构建一个...
本文将深入探讨“消息循环”Looper及其源码解析,帮助开发者更好地理解和应用这一机制。 首先,理解Looper的概念。Looper是Android中的一个类,它的主要职责是管理消息队列(MessageQueue),并不断从队列中取出...
此外,理解Android的Looper和MessageQueue机制也是很重要的。 4. **Android权限管理**:由于涉及到敏感的财务信息,该应用可能需要获取如INTERNET、ACCESS_NETWORK_STATE等权限。开发者需要了解如何在...