V . Looper 子线程
1 . Looper 线程就是在普通线程的基础是哪个 , 加入了 Looper 用于消息调度 , 然后将消息转发给 Handler 进行处理 , 这样就实现了 在其它线程中 , 将任务异步分配给该 Looper 线程 ;
2 . Android 中的主线程本身就是 Looper 线程 , 整个 Looper 循环遍历消息的过程由系统完成 , 用户只需要自定义一个 Handler 成员 , 即可在子线程中调用该 Handler 将消息发送到主线程 , 在主线程执行相关操作 , 实现了将异步任务分配给主线程 , 这是子线程刷新 UI 的重要途径 ;
3 . 普通子线程 转为 Looper 子线程 流程 :
① 定义 Handler 成员变量 : 在线程 Thread 派生类中 , 定义 Handler 类型的成员变量 ;
② Looper 初始化 : 调用 Looper.prepare() 静态方法 , 该方法的作用是创建 Looper 变量 , 存储在了 ThreadLocal 中 , 将当前普通线程转为 Looper 线程 ;
③ 实例化 Handler 成员 : 一定要在 Looper.prepare() 之后实例化成员 , 因为如果在之前实例化 , Handler 与 Looper 无法产生关联 ;
④ 轮询消息队列 : 调用 Looper.loop() 方法 , 轮询消息队列 ( MessageQueue ) ;
4 . 实例化 Handler 成员时机 :
① 实例化时机 : 必须要在调用 Looper.prepare() 之后实例化才可以 , 因为实例化 Handler 对象时 , 会获取当前线程的 Looper , 如果为空 , 直接抛异常 ;
② Looper 对象创建 : Looper.prepare() 的作用就是创建 Looper 对象 , 将其放入 ThreadLocal 对象中存储 , 保证线程有且只有一个 Looper 对象 ;
public class handler { ... //获取 Looper 对象后 , 可以从 Looper 对象中获取 MessageQueue //关联后 , Handler 发送消息时 , 才能将消息精准的发送给 final MessageQueue mQueue; //Handler 需要与线程的唯一 Looper 对象关联 final Looper mLooper; ... public Handler() { ... mLooper = Looper.myLooper() if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } ... mQueue = mLooper.mQueue; ... } ... }
5 . 普通子线程 转为 Looper 子线程 代码示例 :
package kim.hsl.handler; import android.os.Handler; import android.os.Looper; import android.os.Message; import androidx.annotation.NonNull; /** * 将普通线程转为 Looper 线程 * * 1. 定义 Handler 成员 ( 可以定义若干个 ) * 2. Looper.prepare() * 3. 实例化 Handler 成员 * 4. Looper.loop() * * @author hsl */ public class LooperThread extends Thread { /** * 1. 定义时不要实例化 * Handler 实例化需要关联 Looper 对象 * Looper 对象在 Looper */ private Handler handler; @Override public void run() { super.run(); //2. 将线程转为 Looper 线程 //主要是创建 Looper 放入 ThreadLocal 对象中 Looper.prepare(); //3. 创建 Handler 必须在 Looper.prepare() 之后, 否则会崩溃 handler = new Handler(){ @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); //TODO 处理 Handler 相关业务逻辑 } }; //4. Looper 开始轮询 MessageQueue, 将消息调度给 Handler 处理 Looper.loop(); } public Handler getHandler() { return handler; } public void setHandler(Handler handler) { this.handler = handler; } }
VI . Handler 发送 消息 种类
Handler 既可以发送静态的 消息 ( Message ) , 又可以发送动态的 操作 ( Runnable ) ;
当 Handler 所在的 Looper 线程接收到 消息 ( Message ) 时 , Looper 轮询到该 消息 ( Message ) 后 , 执行该消息对应的业务逻辑 , 这些逻辑一般都是在 Handler 中提前定义好的 ;
当 Handler 所在的 Looper 线程接收到 操作 ( Runnable ) 时 , Looper 轮询到该 操作 ( Runnable ) 后 , 直接运行该 Runnable 中的 run() 方法 ;
VII . Handler 机制总结
1 . Handler 机制运行流程 : Message 通过 Handler 发送给 Looper 线程的 MessageQueue , Looper 轮询 MessageQueue 将 Message 交给 Handler 执行 ;
2 . 线程异步调用 ( 作用 ) : 子线程刷新主线程 UI ( 子线程调用主线程 ) , 主线程调用子线程异步网络操作 ( 主线程调用子线程 ) ;
3 . 子线程转 Looper 线程 : ① 定义Handler 成员 ( 可以多个 ) , ② Loop.prepare() , ③ Handler 初始化 ( 必须在 prepare 之后 ) , ④ Looper.loop() ;
4 . 四组件关系 : 1 11线程 ⇔ \Leftrightarrow⇔ 1 11 Looper ⇔ \Leftrightarrow⇔ 1 11 MessageQueue ⇔ \Leftrightarrow⇔ n nn Handler ⇔ \Leftrightarrow⇔ m mm Message ;