android对象池之Message

        在android系统中,message常在多线程之间信息交流中用到,通过Handler来传递线程间的消息(message).今天讨论的是android中的message特性:对象池.

        在android中,google对message有一句这样的英文说明:

       * <p class="note">While the constructor of Message is public, the best way to get
       * one of these is to call {@link #obtain Message.obtain()} or one of the
       * {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull
       * them from a pool of recycled objects.</p>

       上文的意思是: 虽然message的构造方法是对外开放的(public),但是,我们要获取一个message时候最好使用这个方法obtainMessage(),这个方法可以从一个可以复用的对象池中获取你需要的message.

      同上面的意思,我们可以知道,原来message内其实维护了一个对象池,当我们使用完一个message的时候,这个message很有可能就会保存在这个对象池里面,也就是说message里面有一个对象池来保存我们使用过的message.实际上,通过代码,我们可以知道当对象池里面没有我们需要的message时候,会自动new 一个message的. 所以不必担心obtainMessage()获取不了message.

     现在来看看android的message的对象池时如何设计的.实际上,message里面的对象池其实是通过维护一个单项链表来实现的!看看下面就知道来.

     在message里面有一下几个变量的声明和定义:

    /*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 = 50;
      next 指向下一个可用的message;      

      sPoolSync主要用来同步用的,保证多线程安全;

      Message sPool;这里的sPool用来表示当前一个可用的message,请注意这是一个static修饰的message,

     sPoolSize用来记录当前message对象池有多少个messagel . 

     最后解释一下: message里面其实时维护来一个单项链表结构来保存message对象的!next永来指向下一个message对象,这里的sPool很显然就是这个链表的表头.这样以来就可以通过表头顺序遍历整个对象池里面的message.

    上面我说了,当通过这个方法obtainMessage()来获取一个message时候,就会去对象池里面找取(这里就是去这个单向链表中找取),如果对象池里面没有我们需要的message,就会new一个message. 我们来看看代码来证明我所说的.

    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }
      通过上面的代码可以看出:如果链表不为null,就取链表头的message,然后把链表头部下移动. 否在就会new Message().

      最后要说的是,当一个message用完了后是如何加入这个链表的呢? 通过文件Message.java,你会发现在Message里面还定义来一个public的方法:

    public void recycle() {
        clearForRecycle();

        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }
      通过上面的代码可以知道recycle方法其实就是将这个message加入到这个链表(加入到了头部).那么,这个方法时在何时调用的呢?

      实际上,当通过Handler发送一个message的时候,其实是将这个message根据他的延时来决定他的位置,将其添加到一个队列里面的MessageQueue,操作这个MessageQueue不仅仅是这个Handler,还有这个Handler的Looper.

     其实每一个Handler都是需要一个Looper的,往往我们创建一个Handler的时候其实是没有指明他的Looper,不过他会自动获取创建这个Handler的线程的Looper来作为自己的Looper,所以,在android中,往往没有指明Handler的Looper,其实就是用主线程(就是我们常说的ui线程)的Looper.

    刚才我们说了,Handler的Looper其实也操作MessageQueue的,实际上一个Looper就需要一个MessageQueue的,我个人的理解是:Looper的目的就是操作MessageQueue,而Handler控制着Looper和MessageQueue.

   其实时这样的: Handler往MessageQueue里面加入需要处理的message,而Looper从MessageQueue里面取出需要处理的message来开始处理流程.

   在Looper里面其实是通过调用方法loop()来取出需要处理的message,并处理,处理完毕时候就会调用这个message的recycle(),由此来将处理完毕的message加入到对象池的!

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。