android消息池,回转寿司你一定吃过!——Android消息机制(构造)
消息机制的故事寿司陈放在寿司碟上,寿司碟按先后顺序被排成队列送上传送带。传送带被启动后,寿司挨个呈现到你面前,你有三种享用寿司的方法。
将Android概念带入后,就变成了Android消息机制的故事:
寿司碟 ---> 消息(Message)
队列 ---> 消息队列(MessageQueue)
传送带 ---> 消息泵 (Looper)
寿司 ---> 你关心的数据
享用寿司方法 ---> 处理数据方式
暂未找到 Handler 在此场景中对应的实体。它是一个更抽象的概念,它即可以生产寿司,又把寿司送上传送带,还定义了怎么享用寿司。暂且称它为消息处理器吧。
如果打算自己开一家回转寿司店,下面的问题很关键:如何生产寿司(如何构造消息)
如何分发寿司(如何分发消息)
让我们带着这两个问题,去分析一下消息机制源码。
(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 target member on the Message returned.
* @param h Handler to assign to the returned Message object's target 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()就是在取链表头。图示如下:
1
2
3消息池是用链表结构实现的。那 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
next = sPool; //2. 回收的消息成为消息链新头部
sPool = this;
sPoolSize++;
}
}
}正如猜想的那样recycleUnchecked()会将当前消息插入到消息链头部。图示如下
1
2读到这里,我们知道“消息从池中来最终又回到池中去”,那到底消息是在什么时候才会被回收到消息池呢? 好问题!这个问题要等分析完消息分发才能解答。但现在我们可以大胆的猜测一下:承载寿司的碟子会在寿司被享用完之后被厨房回收,那消息是不是再被处理完之后就被回收了?
作者:唐子玄
链接:https://www.jianshu.com/p/134986dfe61b
android消息池,回转寿司你一定吃过!——Android消息机制(构造)相关推荐
- Android线程池封装库
目录介绍 1.遇到的问题和需求 1.1 遇到的问题有哪些 1.2 遇到的需求 1.3 多线程通过实现Runnable弊端 1.4 为什么要用线程池 2.封装库具有的功能 2.1 常用的功能 3.封装库 ...
- (线段树)P5459 [BJOI2016]回转寿司
P5459 [BJOI2016]回转寿司 添加链接描述https://www.luogu.com.cn/problem/P5459 思路:题目意思就是求出有多少个区间和在L~R范围内,这符合线段树的区 ...
- bzoj 4627: [BeiJing2016]回转寿司 -- 权值线段树
4627: [BeiJing2016]回转寿司 Time Limit: 10 Sec Memory Limit: 256 MB Description 酷爱日料的小Z经常光顾学校东门外的回转寿司店. ...
- BZOJ4627 回转寿司 值域线段树
Problem Description 酷爱日料的小Z经常光顾学校东门外的回转寿司店.在这里,一盘盘寿司通过传送带依次呈现在小Z眼前.不同的寿 司带给小Z的味觉感受是不一样的,我们定义小Z对每盘寿司都 ...
- bzoj 4627 回转寿司(权值线段树)
回转寿司 Description 酷爱日料的小Z经常光顾学校东门外的回转寿司店.在这里,一盘盘寿司通过传送带依次呈现在小Z眼前.不同的寿 司带给小Z的味觉感受是不一样的,我们定义小Z对每盘寿司都有一个 ...
- K - 回转寿司(值域段数(板题) + 动态开点)
回转寿司 Description 酷爱日料的小Z经常光顾学校东门外的回转寿司店.在这里,一盘盘寿司通过传送带依次呈现在小Z眼前.不同的寿 司带给小Z的味觉感受是不一样的,我们定义小Z对每盘寿司都有一个 ...
- Bzoj4627 [BeiJing2016]回转寿司
Time Limit: 10 Sec Memory Limit: 256 MB Submit: 329 Solved: 149 [Submit][Status][Discuss] Descript ...
- BZOJ 4627: [BeiJing2016]回转寿司 cdq
4627: [BeiJing2016]回转寿司 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 624 Solved: 273 [Submit][S ...
- 【bzoj 4627】 回转寿司 【BeiJing2016】
Description 酷爱日料的小Z经常光顾学校东门外的回转寿司店.在这里,一盘盘寿司通过传送带依次呈现在小Z眼前.不同的寿 司带给小Z的味觉感受是不一样的,我们定义小Z对每盘寿司都有一个满意度,例 ...
最新文章
- 周杰伦林俊杰李宗盛快失业了!有了AI,未来人人都能秒变作曲家
- POJ3122贪心或者二分(分蛋糕)
- MongoDB 权限
- em标签和strong标签的区别
- 放弃OT了,找了个新框架ThinkCMF
- 微软服务器藏,配置微软CA服务器+SCEP
- 【学术软件】ETPS(English Text Processing Software)
- 如何理解 Linux 中的 load averages
- 一款动态跑路html源码,简单实用,上传解压就完事了
- 分析师称iPhone 13将支持卫星通信,但仅限特定市场
- 25个Linux相关的网站【转】
- 海康威视研究院ImageNet2016竞赛经验分享
- 计算机毕业论文技术可行性怎么写,毕业论文怎么写可行性分析?
- Nginx——自定义错误页面
- python测网速_python一键测试网速
- FER基于卷积神经网络: 处理少量数据和训练样本订单FER with CNN:Coping with few data and the training sample order
- AndroidUSBCamera调用USB摄像头问题
- unix、window、linux、mac介绍
- Java 的核心目的和并发编程
- UML系列——协作图(通信图)collaboration diagram
热门文章
- Scala-高阶函数
- 使用MUI/html5plus集成微信支付需要注意的几点问题
- 第三讲:WCF介绍(3)
- css 设置table样式
- 【Cocos2D-X 学习笔记】Node父类的方法和属性
- oracle学习小知识点总结
- 基于StringTemplate的视图
- Service Worker 离线无法缓存Post请求的问题解决
- “不允许对64位应用程序进行修改”的解决方法 --“Changes to 64-bit applications are not allowed.”
- .Net Framework 4.5.1 安装时遇到严重错误 问题的解决方法