回转寿司你一定吃过!——Android消息机制(构造)

栏目: IOS · Android · 发布时间: 5年前

内容简介:这是“Android消息机制”系列的第一篇文章,系列文章目录如下:将Android概念带入后,就变成了Android消息机制的故事:

这是“Android消息机制”系列的第一篇文章,系列文章目录如下:

  1. 回转寿司你一定吃过!——Android消息机制(构造)
  2. 回转寿司你一定吃过!——Android消息机制(分发)
  3. 回转寿司你一定吃过!——Android消息机制(处理)

消息机制的故事

寿司 陈放在 寿司碟 上, 寿司碟 按先后顺序被排成 队列 送上 传送带传送带 被启动后, 寿司 挨个呈现到你面前,你有三种享用寿司的方法。

将Android概念带入后,就变成了Android消息机制的故事:

消息(Message)
消息队列(MessageQueue)
消息泵 (Looper)

暂未找到 Handler 在此场景中对应的实体。它是一个更抽象的概念,它即可以生产寿司,又把寿司送上传送带,还定义了怎么享用寿司。暂且称它为 消息处理器 吧。

如果打算自己开一家回转寿司店,下面的问题很关键:

  1. 如何生产寿司(如何构造消息)
  2. 如何分发寿司(如何分发消息)

让我们带着这两个问题,去分析一下消息机制源码。 (ps: 下文中的 粗斜体字 表示引导源码阅读的内心戏)

如何构造消息

寿司碟是重复利用的,享用完寿司后,它被清洗,然后被存放起来,以便再次利用。没有哪个老板会在用餐后把寿司碟销毁,下次要用就买新的,这样代价太大。 同样道理, 构造消息对象代价也很大,它是否也像寿司碟一样可以复用?如果是,那消息存放在哪里? 让我们以 Handler.obtainMessage() 为切入点一探究竟:

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

public final class Message implements Parcelable {
  ...
  /**
    * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.
    * @param h  Handler to assign to the returned Message object's <em>target</em> member.
    * @return A Message object from the global pool.
    */
  public static Message obtain(Handler h) {
     Message m = obtain();
     m.target = h;
     return m;
  }
  ...
}
复制代码
  • 其中 Message.target 是一个 Handler 类型的成员变量。 为啥Message要记录构造它的Handler对象? 好问题!但这个问题的解答需要等到分析消息处理的时候才能解答,先留个悬念。
  • 构造消息调用链的终点是 Message.obtain() ,源码如下:
public final class Message implements Parcelable {
    //省略了非关键代码
    ...
    // sometimes we store linked lists of these things
    //指向消息链上下一个消息的引用
    /*package*/ Message next;

    //消息链头部引用,它是静态的,可以被所有消息对象共享
    private static Message sPool;
    //消息链长度
    private static int sPoolSize = 0;

    ...
    /**
     * Return a new Message instance from the global pool. Allows us to
     * avoid allocating new objects in many cases.
     */
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                //1. 定义指向消息链头部引用
                Message m = sPool;
                //2. 定义新的消息链头部
                sPool = m.next;
                //3. 断链
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                //返回消息链头部消息
                return m;
            }
        }
        //如果消息链为空则新建消息
        return new Message();
    }
    ...
}
复制代码
  • 如果对数据结构中的 链表 还有映像, obtain() 就是在取链表头。图示如下:
    回转寿司你一定吃过!——Android消息机制(构造)
回转寿司你一定吃过!——Android消息机制(构造)
回转寿司你一定吃过!——Android消息机制(构造)
  • 消息池是用链表结构实现的。那 Message 一定有一个指向后续结点的“指针” ,果不其然,在其成员变量中找到 Message next;

  • 消息池头指针 sPool 是一个 Message 类型的静态变量,这表示所有 Message 都共享这一个消息池。

  • obtain() 是从消息池中拿消息, 那一定还有一个方法是往池里填消息 ,在 Message 类中搜索 sPool 使用的地方,找到如下这个方法:

/**
     * Recycles a Message that may be in-use.
     * Used internally by the MessageQueue and Looper when disposing of queued Messages.
     */
    void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        //清理消息携带的数据
        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) {
                //1. 回收的消息接入消息链
                next = sPool;
                //2. 回收的消息成为消息链新头部
                sPool = this;
                sPoolSize++;
            }
        }
    }
复制代码
  • 正如猜想的那样 recycleUnchecked() 会将当前消息插入到消息链头部。图示如下
    回转寿司你一定吃过!——Android消息机制(构造)
回转寿司你一定吃过!——Android消息机制(构造)
  • 读到这里,我们知道“消息从池中来最终又回到池中去”, 那到底消息是在什么时候才会被回收到消息池呢? 好问题!这个问题要等分析完消息分发才能解答。但现在我们可以大胆的猜测一下: 承载寿司的碟子会在寿司被享用完之后被厨房回收,那消息是不是再被处理完之后就被回收了?

以上所述就是小编给大家介绍的《回转寿司你一定吃过!——Android消息机制(构造)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

PHP经典实例

PHP经典实例

(美)斯克拉、(美)切贝特伯格 / 李松峰、秦绪文、李丽 / 中国电力出版社 / 2009-10 / 98.00元

PHP经典实例(第2版)能够为您节省宝贵的Web开发时间。有了这些针对真实问题的解决方案放在手边,大多数编程难题都会迎刃而解。《PHP经典实例(第2版)》将PHP的特性与经典实例丛书的独特形式组合到一起,足以帮您成功地构建跨浏览器的Web应用程序。在这个修订版中,您可以更加方便地找到各种编程问题的解决方案,《PHP经典实例(第2版)》中内容涵盖了:表单处理;Session管理;数据库交互;使用We......一起来看看 《PHP经典实例》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

SHA 加密
SHA 加密

SHA 加密工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具