Android 消息队列机制
在非UI线程使用Handler进行线程通信时,一般都需要进行3个步骤:
- 创建Looper
Looper.prepar() - 创建
Handler - 启动消息循环
Looper.loop()
通过这3步,基本就建立好了 Android 的多线程消息通信机制:
- Handler
- MessageQueue
- Looper
- Message
这几者可谓是你中有我,我中有你的存在。通过 Handler 发送 Message 到 Looper 的 MessageQueue 中,待 Looper 的循环执行到 Message 后,就会根据 Message 的 target handler,回调对应 Handler 的 handlerMessage 方法。
例如: Thread-A 拥有一个 Looper,Thread-B 持有一个在 Thread-A 中构造的 Handler,Thread-B 就可以通过这个 Handler 将 Message 发送到 Thread-A 的 Looper 的 MessageQueue 中,然后消息会走到 Thread-A 的 Handler 的 handleMessage 方法。
Looper 原理图

在 Looper 类加载时就会创建一个 ThreadLocal 类型的类变量 sThreadLocal
public final class Looper {
private static final String TAG = "Looper";
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
Looper.prepar()
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 将构造的 looper 存到类变量 sThreadLocal 中
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
// 构建一个 messageQueue 成员
mQueue = new MessageQueue(quitAllowed);
// 将当前线程存入 mThread 中
mThread = Thread.currentThread();
}
在这里面主要执行了 3 步:
- 构建一个 looper
- 构建一个 messageQueue 成员
- 将当前线程存入 mThread 中
- 将构造的 looper 存到类变量 sThreadLocal 中
至此,执行 Looper.praper 的当前线程就会拥有一个 looper 成员了,存放在 Looper 的 sThreadLocal 中。
创建Handler
public Handler(Callback callback, boolean async) {
...
// 通过`Looper.myLooper()` 类方法获取 sThreadLocal 中储存的当前线程的 looper,将这个 looper 绑定到 handler 的成员变量 mLooper 中
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");
}
// 将 mLooper 中的 messageQueue 绑定到 handler 的成员变量 mQueue 中
mQueue = mLooper.mQueue;
...
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
Looper.loop()
声明一个局部常量
final Loop me = myLoop()myLoop()将返回当前线程的looper成员
声明一个局部常量
final MessageQueue queue- 将me.mQueue赋值给queue
进入无限循环
//进入无限循环
for (;;) {
//取出一条消息
Message msg = queue.next();
//没有消息就阻塞
if (msg == null) {
return;
}
... //分发消息
try {
msg.target.dispatchMessage(msg);
//msg.target是一个Handler对象
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
... //回收消息
msg.recycleUnchecked();
通过
Message.obtain()获取的消息,需要使用Handler.sendMessage()插入到消息队列。通过
Handler.obtainMessage()获取的消息,可以使用message.sendToTaget()插入到消息队列。
Android 消息队列机制的更多相关文章
- ZWave 中的消息队列机制
文章主题 在我们的日常编程中,对消息队列的需求非常常见,使用一个简洁.高效的消息队列编程模型,对于代码逻辑的清晰性,对于事件处理的高效率来说,是非常重要的.这篇文章就来看看 ZWave 中是通过什 ...
- Android消息队列和Looper
1. 什么是消息队列 消息队列在android中对应MessageQueue这个类,顾名思义,消息队列中存放了大量的消息(Message) 2.什么是消息 消息(Message)代表一个行为(what ...
- Android 消息分发机制
Android 中针对耗时的操作,放在主线程操作,轻者会造成 UI 卡顿,重则会直接无响应,造成 Force Close.同时在 Android 3.0 以后,禁止在主线程进行网络请求. 针对耗时或者 ...
- Android开发学习—— 消息队列
###主线程不能被阻塞* 在Android中,主线程被阻塞会导致应用不能刷新ui界面,不能响应用户操作,用户体验将非常差* 主线程阻塞时间过长,系统会抛出ANR异常* ANR:Application ...
- Android 开发笔记 “Android 的消息队列模型”
Android是参考Windows的消息循环机制来实现Android自身的消息循环的. Android通过Looper.Handler来实现消息循环机制,Android消息循环是针对线程的(每个线程都 ...
- Android 的消息队列模型
Android 的消息队列模型 Android是参考Windows的消息循环机制来实现Android自身的消息循环的. Android通过Looper.Handler来实现消息循环机制,Andr ...
- Android HandlerThread 消息循环机制之源代码解析
关于 HandlerThread 这个类.可能有些人眼睛一瞟,手指放在键盘上,然后就是一阵狂敲.立即就能敲出一段段华丽的代码: HandlerThread handlerThread = new Ha ...
- Window Azure ServiceBus Messaging消息队列技术系列1-基本概念和架构
前段时间研究了Window Azure ServiceBus Messaging消息队列技术,搞了很多技术研究和代码验证,最近准备总结一下,分享给大家. 首先,Windows Azure提供了两种类型 ...
- 跟我一起学WCF(1)——MSMQ消息队列
一.引言 Windows Communication Foundation(WCF)是Microsoft为构建面向服务的应用程序而提供的统一编程模型,该服务模型提供了支持松散耦合和版本管理的序列化功能 ...
随机推荐
- 小程序组件 Vant Weapp 安装
文件夹的名称必须是英文 第一步:npm init -y 第二步:npm i vant-weapp -S --production
- 使用pandas中的raad_html函数爬取TOP500超级计算机表格数据并保存到csv文件和mysql数据库中
参考链接:https://www.makcyun.top/web_scraping_withpython2.html #!/usr/bin/env python # -*- coding: utf-8 ...
- CodeVS 1013&1029
若干二叉树遍历的数据结构题. Problem 1013 传送门:http://codevs.cn/problem/1013/ 本题是一个数据结构——二叉树遍历问题. 对二叉树,给定中序遍历序列(In- ...
- 【hihocoder 1296】数论三·约瑟夫问题
[题目链接]:http://hihocoder.com/problemset/problem/1296 [题意] [题解] [Number Of WA] 0 [完整代码] #include <b ...
- 【codeforces 793C】Mice problem
[题目链接]:http://codeforces.com/contest/793/problem/C [题意] 给你每个点x轴移动速度,y轴移动速度; 问你有没有某个时刻,所有的点都"严格& ...
- h264封包介绍
这个要看你怎么理解了.和MPEG2.MPEG4相比,H.264字节流中帧的形式发生了变化.以视频帧为例,MPEG2和MPEG4字节流在传输的时候提取帧的关键参数,将其封装入传输包首部,比如TS包或RT ...
- hdu 4858 容器的简单模拟
我用临接表模拟容器超时 #include<stdio.h> #include<string.h> #include<vector> using namespace ...
- FZU - 2062 - Suneast & Yayamao
先上题目: Problem 2062 Suneast & Yayamao Accept: 146 Submit: 319Time Limit: 1000 mSec Memory L ...
- CLR与Netframework版本的关系
CLR有3个版本,详细地址看微软官方文档
- MySQL命名、设计及使用规范《MySQL命名、设计及使用规范》
数据库环境 dev:开发环境,开发可读写,可修改表结构.开发人员可以修改表结构,可以随意修改其中的数据但是需要保证不影响其他开发同事. qa:测试环境,开发可读写,开发人员可以通过工具修改表结构. s ...