该篇主要介绍的是Handler 消息机制中的Message 类。Message 源码分析,带你从源码层面去解读Handler 机制中的Message 类,了解Message 类是如何实现消息复用的?这里面涉及到的是什么设计模式?了解 Message 类的正确使用姿势 。 Message 类即是消息的载体,将要传递的数据打包进Message 对象进行发送,在Handler 的 handleMessage(Message msg) 方法中接收发送的Message 对象 问:在Handler 的使用过程中,Message有几种创建方式?哪种效果更好,为什么? 使用 Message 默认的构造函数可以非常简单的创造出一个Message 实例。 虽然Message的构造函数是公共的,我们可以通过new 关键字来自行创建一个Message 对象,但是系统更推荐我们使用 {Message.obtain()}或{Handler.obtainMessage()}相关的方法获取对象。在Message 的类注释和构造函数注释上均已说明。 android.os.Handler#obtainMessage() 而当我们使用Handler 获取一个Message 对象时,其内部调用的同样也是Message 的相关方法。以android.os.Handler#obtainMessage()方法为例: 当我们在创建一个Message 时,系统推荐使用{Message.obtain()}或{Handler#obtainMessage.obtainMessage()} 系列的方法获取一个Message 对象,不过不管使用哪种形式的方法,最后都会执行到 android.os.Message#obtain() 这个方法,而不同参数的重载方法无非是给我们在使用的过程中提供一些便捷而已。 Message 内部是如何进行优化的呢? Message 内部有一个全局的缓存池 sPool,用于保存回收的Message 对象。它是一个链表的结构,其 next 属性指向下一个Message 缓存对象,以这样的方式把所有缓存的Message 对象都串在了一起。这种缓存池的实现方式也正是享元模式的一种。 在 obtain() 方法内部,会先从缓存池中获取Message 对象,如果没有则再去创建一个新消息返回。在消息转发完成后,调用 recycleUnchecked() 方法对使用的消息进行资源释放、回收,插入到缓存池中以备再用,节约因频繁创建对象带来的内存开销。 缓存池(sPool)本质上是一个消息链表,当调用obtain()方法时,检查缓存池中是否有可用的Message 对象 该方法的目的就是回收Message 对象,以供循环使用。在处理排队的消息时,recycleUnchecked() 方法由MessageQueue和Looper内部使用。在Loop的loop() 方法中,在消息发送完毕后,会调用 msg.recycleUnchecked() 来回收消息。 recycleUnchecked() 方法内部可以分为2个步骤:文章目录
消息的获取
new一个Message实例(不推荐)
Message message = new Message();
/** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}). */ public Message() { }
通过Message的obtain相关的静态方法(推荐)
通过Handler的obtain 相关的方法(推荐)
android.os.Handler#obtainMessage(int)
android.os.Handler#obtainMessage(int, java.lang.Object)
android.os.Handler#obtainMessage(int, int, int)
android.os.Handler#obtainMessage(int, int, int, java.lang.Object)/** * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this). * If you don't want that facility, just call Message.obtain() instead. */ public final Message obtainMessage() { return Message.obtain(this); }
结构
// 用户定义的消息码,以便收件人可以识别此消息的含义 public int what; // 系统给我们提供的两个用来做数据传递的简单类型 public int arg1; public int arg2; // 要发送给接收者的数据对象。 public Object obj; // 触发时间,在执行入队操作时根据提供的时间来对消息进行排序、插队 /*package*/ long when; // 目标Handler,即哪个Handler对此消息进行负责,发送消息和处理响应 /*package*/ Handler target; // Message 是一个消息链表,持有下一个节点的引用 /*package*/ Message next; // 锁对象,用来维持线程同步的 public static final Object sPoolSync = new Object(); // 对象缓存池,用于存放回收的Message,使用享元模式来节省资源开销。其实现方式采用的是链表的形式。 private static Message sPool; // 当前缓存的可用Message 数量 private static int sPoolSize = 0; // 最大缓存对象数 private static final int MAX_POOL_SIZE = 50;
复用机制(享元模式)
从缓存池获取消息
/** 1. Return a new Message instance from the global pool. Allows us to 2. avoid allocating new objects in many cases. */ public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; m.flags = 0; // clear in-use flag sPoolSize--; return m; } } return new Message(); }
a. 把sPool 赋值给一个的对象;
b. 将持有的next 对象指向 sPool,成为缓存池新的链表头。
c. 把新的message 的 next 置为null , 因为message 还持有下一个节点的引用,也就意味着把新的 Message 断链,形成一个独立的消息对象。
d. 缓存池的可用数量减1消息回收
void recycleUnchecked() { // 1.清除所有的特征信息。 flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; sendingUid = -1; when = 0; target = null; callback = null; data = null; // 2.插入到缓存池中进行回收,循环使用 synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { // 把当前对象当做对象池的链表头 next = sPool; sPool = this; sPoolSize++; } } }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算