Handler通信机制下创建Message对象的几种方法比较

我们在使用Handler通信的时候,通常还会创建一个Message对象用于对消息的封装。那创建一个Message对象有哪些方式呢?
我们常用的创建Message对象的方式有如下三种:

	方式1Message message = new Message();
	方式2Message message = Message.obtain();
	方式3Message message = new Handler().obtainMessage();

其中方式1,是我们最常用的方式,通过Message的无参构造函数创建一个Message对象:

	public Message() {
    }

这个没什么好说的,我们每new一次,就会在内存中创建一个Message对象。

方式2,Message.obtain()及其系列的重载方法,我们先看看他的无参方法的源码实现:

    public static Message obtain() {
    	//sPoolSync参数是一个Object对象,用来同步保证线程安全。
        synchronized (sPoolSync) {
        	sPool是就是handler.dispatchMessage()方法执行后,通过recycleUnchecked回收用以复用的Message
            if (sPool != null) {
                Message m = sPool;//直接从本地获取一个message对象
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                //每调用一次该方法,就将新的message对象加入Message池子,sPoolSize就减少一个
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

sPoolSync参数是一个Object对象,用来同步保证线程安全。sPool是一个Message 对象,sPoolSize是一个整体上控制Message对象数量的参数,防止通过该方法创建的Message对象过多。另外,与之相关联的方法还有以下几个方法:

	public void recycle() {
        if (isInUse()) {
            if (gCheckRecycle) {
                throw new IllegalStateException("This message cannot be recycled because it "
                        + "is still in use.");
            }
            return;
        }
        recycleUnchecked();
    }
    
    void recycleUnchecked() {
        // 当我们使用完Message对象的时候,系统就回收Message对象,但这里的回收跟JVM虚拟机的回收不一样,
        //他并不是直接将Message对象置为空,而是将Message对象里面的各参数置为初始状态。
        flags = FLAG_IN_USE;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        sendingUid = UID_NONE;
        workSourceUid = UID_NONE;
        when = 0;
        target = null;
        callback = null;
        data = null;
        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                //完成回收后,再将Message对象添加到池子里面去,恢复数量,方便下次获取。
                sPoolSize++;
            }
        }
    }

这两个方法的作用就是当我们使用完通过方式2创建的Message对象后,系统会自动回收Message对象,但这里的回收并不是直接将Message对象清空置为null,而是清空Message对象里面的所有信息,然后再将其添加到系统的sPoolSize中去,方便下次直接使用。
简单的说,使用方式2创建Message对象的好处是Message对象可以重复使用,可以免除一直new Message对象造成无谓的内存压力(不断新建销毁对象),实现 类似于线程池的功能。

方式2也是Google推荐的方式,Handler的send系列方法和post系列方法内部的message对象都是使用这个方式获取的。

方式3、new Handler().obtainMessage()及其系列的重载方法,我们先看看他的无参方法的源码实现:

	public final Message obtainMessage(){
        return Message.obtain(this);
    }

Message.obtain(this)方法具体 如下:

	public static Message obtain(Handler h) {
        Message m = obtain();
        m.target = h;//在这里,实现了Message对象与Handler对象的绑定
        return m;
    }

我们可以看到,new Handler().obtainMessage()方法内部最终还是调用了obtain()方法,又回到了方式2,这跟方式2创建Message对象是一样的,本质上没有区别。

因此我们在创建Message对象时,尽可能的使用方式2,以减少内存开销。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值