Android基础之Handler机制(二)之Message源码分析

基于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控制,请小心使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值