文章目录
- 一、Looper 初始化
- 二、Looper 遍历消息队列 MessageQueue
- 三、完整 Looper 代码
一、Looper 初始化
Looper 是 线程本地变量 , 在每个线程中 , 可以通过线程调用 ThreadLocal 变量的 get 方法获取该线程对应的对象副本 , 调用 ThreadLocal 变量的 set 方法 , 设置该线程对应类型的对象副本 ;
Looper 调用 prepare 方法进行初始化 , 在该方法中处理 线程本地变量的先关初始化与设置 ,
如果之前已经初始化过 , 本次调用 prepare 方法是第二次调用 , 则会 抛出异常 ,
如果之前没有初始化过 , 那么创建一个 Looper , 然后调用线程本地变量 ThreadLocal 的 set 方法 , 将该 Looper 对象设置成线程本地变量 ;
代码语言:javascript复制 /**
* 一个线程只能有一个 Looper
* 使用 ThreadLocal 来保存该 Looper
* 是线程内部存储类 , 只能本线程才可以得到存储的数据 ;
*/
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
/**
* 准备 Looper 方法
*/
public static void prepare(){
System.out.println("prepare 创建 Looper ");
// 先进行判断 , 如果当前线程已经有了 Looper , 那就抛出异常
if(sThreadLocal.get() != null){
throw new RuntimeException("当前线程已存在 Looper");
}
// 如果不存在 Looper , 就创建一个 Looper
sThreadLocal.set(new Looper());
}
二、Looper 遍历消息队列 MessageQueue
在 Looper 线程中 , 最后一句代码肯定是 Looper.loop() , 执行该方法后 , 就开启了一个无限循环 ,
不断从 消息队列 MessageQueue 中获取消息 , 然后发送给该 消息 Message 对应的 Handler ,
哪个 Handler 发送的消息 , 就将消息在送回给哪个 Handler ;
消息同步 : 当 消息队列 MessageQueue 为空时 , 无法从消息队列中获取数据 , 此时线程会 阻塞 , 直到有新的消息到来后 , 解除阻塞 ;
Looper 循环遍历消息队列部分代码 :
代码语言:javascript复制 /**
* 不断从 消息队列 MessageQueue 中取出 Message 消息执行
*/
public static void loop(){
System.out.println("开始无限循环获取 Message");
// 获取当前线程的 Looper
Looper looper = Looper.looper();
// 从当前线程的 Looper 获取 消息队列 MessageQueue
MessageQueue messageQueue = looper.mQueue;
// 不断从 消息队列中获取 消息 , 分发到发送消息的 Handler 中执行
for(;;){
// 获取消息队列中的第一个消息
Message next = messageQueue.next();
// 分发到发送该消息的 Handler 中执行
next.target.handleMessage(next);
}
}
三、完整 Looper 代码
代码语言:javascript复制package kim.hsl.handler;
public class Looper {
/**
* 一个线程只能有一个 Looper
* 使用 ThreadLocal 来保存该 Looper
* 是线程内部存储类 , 只能本线程才可以得到存储的数据 ;
*/
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
/**
* 消息队列
*/
public MessageQueue mQueue;
/**
* Looper 构造函数
*/
private Looper(){
mQueue = new MessageQueue();
}
/**
* 获取当前线程对应的 Looper
* @return
*/
public static Looper looper(){
return sThreadLocal.get();
}
/**
* 准备 Looper 方法
*/
public static void prepare(){
System.out.println("prepare 创建 Looper ");
// 先进行判断 , 如果当前线程已经有了 Looper , 那就抛出异常
if(sThreadLocal.get() != null){
throw new RuntimeException("当前线程已存在 Looper");
}
// 如果不存在 Looper , 就创建一个 Looper
sThreadLocal.set(new Looper());
}
/**
* 不断从 消息队列 MessageQueue 中取出 Message 消息执行
*/
public static void loop(){
System.out.println("开始无限循环获取 Message");
// 获取当前线程的 Looper
Looper looper = Looper.looper();
// 从当前线程的 Looper 获取 消息队列 MessageQueue
MessageQueue messageQueue = looper.mQueue;
// 不断从 消息队列中获取 消息 , 分发到发送消息的 Handler 中执行
for(;;){
// 获取消息队列中的第一个消息
Message next = messageQueue.next();
// 分发到发送该消息的 Handler 中执行
next.target.handleMessage(next);
}
}
}