在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加入到对象池的!

更多相关文章

  1. android 数据传输之JSON
  2. Android的Message机制
  3. Android(安卓)NDK c调用java代码
  4. Android的移动存储解决方案之SharedPreferences
  5. Android(安卓)Service生命周期
  6. android中视频播放的处理
  7. Bitmap和Drawable相互转换方法
  8. 配置flutter --Android(安卓)license status unknown.sdk 没有to
  9. 调用Android自带的联系人选择界面

随机推荐

  1. 用 19 张思维导图描述Spring Cloud的概念
  2. 云栖大会 | Apache Spark 3.0 和 Koalas
  3. Android 高通Camx架构学习 - 第1章
  4. 如何为Kafka集群选择合适的Topics/Partit
  5. 你还在使用 JDK 7?JDK 13 都已经来了!五大
  6. SpringBoot + Mybatis + Druid + PageHel
  7. 华为核心交换机配置mac地址白名单接入
  8. RabbitMQ Linux一键安装脚本定制
  9. 从Storm到Flink,有赞五年实时计算效率提升
  10. 深入理解 Apache Spark Delta Lake 的事