主要的类:
Handler
Looper
Messge
MessageQueue
Handler:
public class Handler {
/**
* @author kongalong
*
* 这个接口的意义是:起到一个拦截msg的作用,根据他的handleMessage()
* 返回值来决定是否调用Handler的handleMessage()
* 并且给用户提供实现接口的方法,来处理消息,而不用派生Handler的子类
*/
public interface Callback {
public boolean handleMessage(Message msg);
}
public Callback mCallback;
//持有一个线程中唯一一个Looper引用
public Looper mLooper;
//消息队列
public MessageQueue mQueue;
/**
* 构造方法: 初始化looper,通过Looper.myLooper()获取Looper引用
* ,这种方式获取的Looper是当前线程唯一的Looper,通过ThreadLocal实现
*
* 通过looper初始化MessageQueue
* @throws Exception
*
*/
public Handler() throws Exception {
// 通过Looper静态方法获取looper 也就是通过ThreadLocal获取当前线程的looper
mLooper = Looper.myLooper();
if (mLooper == null) {
// 这里抛异常,不能在没有创建looper的线程中创建Handler用
// 没有looper,handler也就没有存在的意义
throw new Exception("不能再没有Looper的线程中创建Handler");
}
// 获取looper中的MessageQueue
mQueue = mLooper.mQueue;
}
// 这个用户传过来的looper不能为空
public Handler(Looper looper) throws Exception {
mLooper = looper;
if(mLooper == null){
throw new Exception("不能再没有Looper的线程中创建Handler");
}
// 获取looper中的MessageQueue
mQueue = mLooper.mQueue;
}
public Handler(Callback callback) throws Exception {
// 调用无参构造方法获取looper
this();
mCallback = callback;
}
/**
*
*
* 先判断Message中的callback也就是Runnable是否为空,不为空就调用用户实现的run方法,就结束
* 否则判断当前Handler的mCallback是否为空,不为空就调用用户实现Callback中的handleMessage()方法
* mCallback.handleMessage()有返回值,true,直接结束,false,还会调用handler的handleMessage()
* 这些调用的方法都是回调用户实现的方法才有意义
*
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
// 调用用户实现的Runnable的run方法
private void handleCallback(Message msg) {
msg.callback.run();
}
// 用户需要实现
public void handleMessage(Message msg) {
}
/**
* 向MessageQueue发送消息
*
* 原版是里面调用了sendMessageDelayed(Message msg, long delayMillis)有时间参数的,
* 可以定时发送消息。为了简单点,这里就没有加入这个参数
*
* 为了简化,直接 调用MessageQueue的enqueueMessage() 向里MessageQueue插入消息
*
*/
public void sendMessage(Message msg) {
MessageQueue queue = mQueue;
// 把当前Handler赋给Message的target,
msg.target = this;
//把消息插入消息队列
queue.enqueueMessage(msg);
}
/**
* 原版是调用Message的obtain()生成一个消息,Message中有一个Message sPool成员,作用是缓存Message的意思,
* 如果sPool不为空就把sPool作为消息返回,否则直接new Message(); 目的是获取一个Message对象
*
* 这里为了简单,就直接new Message()了,
* 并且把Runnable赋值给Message的callback,这个Runnable就是用户实现Runnable的对象
*
* 最后还是调用sendMessage();
*
*/
public void post(Runnable r) {
Message msg = new Message();
msg.callback = r;
sendMessage(msg);
}
}
Looper:
public class Looper {
/**
* 使用ThreadLocal来存储looper,保证每一个线程有独自的looper
* 为什么使用ThreadLocal,如果不使用,要保证每个线程都有独自的looper,
* 可能需要一个全局LooperManager来管理Looper,也是需要使用map的方式存储looper,
* 使用当前线程作为key,looper作为value,但这一切threadLocal都实现好了。
*/
static final ThreadLocal<Looper> mThreadLocal = new ThreadLocal<Looper>();
public MessageQueue mQueue;
/**
* 在构造函数中初始化消息队列
*/
public Looper() {
mQueue = new MessageQueue();
}
/**
* 创建Looper并添加到ThreadLocal
*/
public static void prepare() {
// 添加Looper
mThreadLocal.set(new Looper());
}
// 从ThreadLocal获取Looper
public static Looper myLooper() {
return mThreadLocal.get();
}
// 循环取出消息
public static void loop() {
// 获取Looper
Looper tempLooper = myLooper();
// 获取MessageQueue
MessageQueue tempMQueue = tempLooper.mQueue;
for (;;) {
// 取出消息
Message msg = tempMQueue.next();
// 唯一跳出循环的条件
if (msg == null) {
return;
}
// 调用Handle的dispatchMessage
msg.target.dispatchMessage(msg);
}
}
/**
* 退出loop();通过设置MessageQueue中的mQuitting来退出MessageQueue中的next(),从而退出loop()
*/
public void quit() {
mQueue.setMQuitting(true);
}
}
Message:
public class Message {
/**
* 定义消息携带的数据
*/
public Message next;
public Handler target;
public int what;
public Object obj;
Runnable callback;
}
MessageQueue:
public class MessageQueue {
// 退出next()的标志
private boolean mQuitting;
public void setMQuitting(boolean mQuitting) {
this.mQuitting = mQuitting;
}
//相当于头指针 从这里开始遍历寻找和插入消息
Message mFirstMessage;
/**
* 插入消息 不需看懂里面的逻辑,只是向链表插入Message,在Handler的sendMessage()中调用
*/
public void enqueueMessage(Message msg) {
Message tempMessage = mFirstMessage;
//没有实现队列的先进先出,没有同步
//第一个消息来了
if (tempMessage == null) {
mFirstMessage = msg;
msg.next = null;
} else {
// 插入消息
Message prevMsg;
for (;;) {
prevMsg = tempMessage;
tempMessage = tempMessage.next;
// 遍历到链表尾部
if (tempMessage == null) {
break;
}
}
// 新的消息接在尾部
prevMsg.next = msg;
msg.next = null;
}
}
/**
* 取出消息 ,只是循环从链表取出Message,在Looper的loop中调用
* @return
*/
Message next() {
/**
* 没有实现队列的先进先出,没有同步, 只是演示一下,没什么影响。。
*/
for (;;) {
Message tempMessage = mFirstMessage;
if (tempMessage != null) {
mFirstMessage = tempMessage.next;
return tempMessage;
}
// 退出死循环的唯一条件,,通过looper设置
if (mQuitting) {
return null;
}
}
}
}
public class client{
static Handler handler;
public static void main(String[] args) throws Exception {
// 创建当前线程的Looper,和 messageQueue
Looper.prepare();
/**
* 以下模拟各种使用方法
*
* 都需要handler,并在Handler的构造方法获取当前线程的looper,从而获取messageQueue
*
*/
// 派生Handler子类的用法
handler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 1) {
// System.out.println("message==="+msg);
System.out.println(Thread.currentThread());
}
}
};
// 在子线程中发送消息
new Thread() {
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread());
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
}
}.start();
// 重写Runnable run()的用法
// 里面会把Runnable封装成Message, 这不是开启新线程,不知道为什么使用Runnable,感觉用别的接口也行
handler.post(new Runnable() {
@Override
public void run() {
// System.out.println("message===run");
}
});
// 开启循环,取出消息
Looper.loop();
/**
* 小结:
* 一个线程存数据,另一个线程取数据,中间的媒介就是Message, 这样就实现了线程间的通行,
*
* 使用Message有解耦的作用,使得两个线程依赖不是那密切,两个对象之间通过第三方对象(一般就是抽象)产生依赖关系,
* 这也是遵循设计模式的依赖倒置原则
*
* 还有一个关键的东西就是ThreadLocal,使用ThreadLocal保存Looper,使用当前线程作为键,保证了每个线程都有自己Looper,不受其他线程影响。
*
* 有个疑问? 在Android中,loop是个死循环,主线程为啥不会卡死?具体的需要理解Linux epoll,管道模型了
*/
}
}
Android 消息机制过了一遍,加深对其理解
github:https://github.com/along-KAL/SimulativeAndroidMessage