1、首先通过Looper.prepare生成了一个全局的Looper对象,同时也生成了一个MessageQueue消息队列对象
2、模拟Activity中创建Handler对象,在Handler对象创建的同时,获取到了当前线程的Looper,并且根据当前线程的Looper获取到了当前线程的MessageQueue消息队列
3、重写Handler的handlerMessage(Message message)方法,这个方法用于子类处理子线程的消息。
4、创建子线程,第一步就是实例化Message消息,第二步设置Message的标志位,和Message携带的一个消息内容。第三部通过第二步中的handler对象调用sendMessage(Message message)方法发送Message消息到MessageQueue消息队列中
4.1 在sendMessage(Message message)方法中有一个标志位,用于表示当前的Handler对象,也就是第二步中的Handler对象,然后就是通过调用MessageQueue的enqueueMessage(Message message)方法将Message消息放入队列
4.2 MessageQueue的enqueueMessage(Message message)方法,使用了阻塞队列的方式将Message消息存入阻塞队列中
5、启动子线程后,就调用Looper的loop()方法,对MessageQueue消息队列进行轮询,并取出消息
5.1 Looper的loop()方法
第一步就是从全局ThreadLocalMap中获取唯一的Looper对象
全局ThreadLocalMap:
private static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
从全局ThreadLocalMap中获取唯一的Looper对象
public static Looper myLooper(){
return sThreadLocal.get();
}
//这些代码知识部分代码片段,并非完整的
//从全局ThreadLocalMap中获取唯一:Looper对象
Looper me = myLooper();
第二步,从Looper对象中获取全局唯一消息队列MessageQueue对象
MessageQueue queue = me.messageQueue;
第三步,轮询取出消息
//轮询
Message msg;
for (;;){
//消息队列取消息
msg = queue.next();
if (msg == null || msg.target == null){
continue;
}
//获取到发送消息的msg.target (handler)本身,然后分发消息
msg.target.dispatchMessage(msg);
上一步中从消息队列取消息,通过获取的全局MessageQueue对象(第5步中的第二步)调用MessageQueue的next方法,还是采用阻塞队列的方式,将消息从阻塞队列取出,分发消息:
//获取到发送消息的msg.target (handler)本身,然后分发消息
msg.target.dispatchMessage(msg);
然后在这里的分发消息这里,我们看一下代码:
/**
* 分发消息
*/
public void dispatchMessage(Message message){
handleMessage(message);
}
可以看到,他这里又回调了handleMessage(Message message)方法,所以我们就可以回到第三步里面,对子线程的消息进行处理。
单元测试代码:
package com.example.myhandler;
import org.junit.Test;
/**
* com.example.myhandler
*
* @author yueqingh
* @date 2021/10/14
*/
public class ActivityThread {
@Test
public void main(){
//创建全局唯一的主线程Looper对象,以及MessageQueue消息队列对象
Looper.prepare();
//模拟Activity中,创建Handler对象
final Handler handler = new Handler(){
@Override
public void handleMessage(Message message) {
super.handleMessage(message);
switch (message.what){
case 1:
System.out.println(message.obj.toString());
break;
case 2:
System.out.println(message.obj.toString());
break;
}
}
};
//子线程1发送消息
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = new Message();
msg.what = 1;
msg.obj="子线程1执行UI操作";
handler.sendMessage(msg);
}
}).start();
//子线程2发送消息
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = new Message();
msg.what = 2;
msg.obj = "子线程2执行UI操作";
handler.sendMessage(msg);
}
}).start();
//轮询,取出消息
Looper.loop();
}
}
测试结果:
1、单元测试方法测试结果
2、在Activity中的测试结果:(注意,这里使用手写的handler方式的时候,图像不显示,在网上查了一下,好像是Google限制了隐藏方法通过反射调用)
不过,通过log信息可以看出自己手写的Handler是运行成功了的