Android基础之Handler机制(二)之Message源码分析
程序员文章站
2022-07-14 16:45:28
...
基于8.0.0源码
##定义##
Defines a message containing a description and arbitrary data object that can be sent to a {@link Handler}. This object contains two extra int fields and an extra object field that allow you to not do allocations in many cases.
个人理解:
定义一个可以被发送到Handler的包含一个描述和任意类型数据对象的消息. 这个消息对象包含两个额外的int属性和一个额外的object属性可以让我们在大多情况下不需要做过多配置.
方法细节##
类实现
我们知道在Java中传输数据要实现序列化就是实现Serializable,Android中提倡使用Parcelable.
- Message类实现了Parcelable接口
- 重写describeContents()和writeToParcel(Parcel dest, int flags) 方法
###构造方法###
-
空参的构造方法
-
系统提示创建一个Message首选的方法应该是Message.obtain()方法.
-
为什么要用obtain()方法呢?我们进源码看下
/** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. * 从缓存池中返回一个新的Message对象实例,让我们避免了在大多数情况下new一个新的对象 */ public static Message obtain() { //上锁,同一时间只有一个线程能进入 synchronized (sPoolSync) { //如果pool不为空,就说明缓存池中有对象 if (sPool != null) { //把sPool的引用赋值给m Message m = sPool; sPool = m.next; //m的next置为null m.next = null; //清除Message的标记,不在in-use状态 m.flags = 0; // clear in-use flag sPoolSize--; return m; } } //如果为空,则返回一个新的Message对象 return new Message(); }
其实就是内部维护了一个链表形式的Message对象缓存池
###保存数据的相关属性和方法###
-
int what
- 用于辨别不同消息的标识属性
-
int arg1 ,int arg2
- 简单整数型属性
-
Object obj
- 我们开发可以自己定义的属性
-
Bundle data
- 如果有其他数据,可以用bundle来传输
- 把需要传输的数据用Bundle来封装,然后再调用msg的setData方法设置进去
obtain 方法
-
static Message obtain()
- 空参方法,一般用来创建Message
-
static Message obtain(Message orig)
- 传入msg参数
- 把传入orig中的数据拷贝到一个新的Msg对象中, 返回的这个新的对象是从Msg的缓存池中获取的.
-
static Message obtain(Handler h)
- 传入Handler 参数
- 从Msg的缓存池中返回一个Msg对象,并且把该Msg对象的target属性的引用指向 入参handler,这样该Msg就持有了Handler的引用
-
static Message obtain(Handler h, Runnable callback)
- 传入Handler参数,Runnable 参数
- 当Loop分发消息时,如果callback不为空,那么这个Runnable对象就不会调用Handler的handlerMessage方法.而是在已经回到创建Handler的那个线程上运行Runnable对象.
-
static Message obtain(Handler h, int what)
- 传入 Handler,消息标识 what
- 把从缓存池中返回的Msg的属性target和what的引用指向这两个参数
-
static Message obtain(Handler h, int what, Object obj)
- 传入 Handler,消息标识 what,自定义obj
- 把从缓存池中返回的Msg的属性target和what和obj的引用指向这三个参数
-
static Message obtain(Handler h, int what, int arg1, int arg2)
- 同上解释,参数赋值
-
static Message obtain(Handler h, int what,
int arg1, int arg2, Object obj)- 同上解释,参数赋值
缓存池回收方法
-
void recycle()
//往缓存池中添加一个Msg实例, public void recycle() { //判断Msg是否在使用 if (isInUse()) { //这里的gCheckRecycle标识位是指是否大于5.0版本,大于的话是true,小于的话是false if (gCheckRecycle) { throw new IllegalStateException("This message cannot be recycled because it " + "is still in use."); } return; } recycleUnchecked(); }
-
最终调用 recycleUnchecked()
//回收一个可能正在被使用的Msg,MessageQueue和Looper都会调用这个方法去回收Msg void recycleUnchecked() { // Mark the message as in use while it remains in the recycled object pool. // Clear out all other details. 归零Msg所有属性 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++; } } }
Msg异步传输/同步传输
-
boolean isAsynchronous()
- 判断Msg是否是异步传输,如果是异步传输就返回true
-
void setAsynchronous(boolean async)
- 设置Msg是否为异步传输
- 如果设置成异步传输,Msg在MessageQueue中的位置可能被打乱,Msg对象将不受Looper控制,请小心使用
上一篇: 注释转换-小程序
推荐阅读
-
Android Studio 之 Android消息机制 之简单Demo --- 使用Handler和Message类来完成消息传递
-
Android消息机制三剑客之Handler、Looper、Message源码分析(一)
-
Android消息机制原理,仿写Handler Looper源码解析跨线程通信原理--之仿写模拟Handler(四)
-
Android多线程(二)消息处理机制---Handler、Message、Looper源码原理解析
-
Android源码分析之Handler机制
-
Handler机制之MessageQueue源码分析
-
Handler机制之Message源码解析
-
Android基础之Handler机制(二)之Message源码分析
-
零基础学Android源码之Handler机制
-
Android基础之Handler机制(三)之MessageQueue源码分析