前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Android 异步操作】手写 Handler ( 循环者 Looper | Looper 初始化 | Looper 遍历消息队列 MessageQueue )

【Android 异步操作】手写 Handler ( 循环者 Looper | Looper 初始化 | Looper 遍历消息队列 MessageQueue )

作者头像
韩曙亮
发布2023-03-28 18:48:27
4230
发布2023-03-28 18:48:27
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

一、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);
        }
    }

}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-11-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、Looper 初始化
  • 二、Looper 遍历消息队列 MessageQueue
  • 三、完整 Looper 代码
相关产品与服务
消息队列
腾讯云消息队列 TDMQ 是分布式架构中的重要组件,提供异步通信的基础能力,通过应用解耦降低系统复杂度,提升系统可用性和可扩展性。TDMQ 产品系列提供丰富的产品形态,包含 CKafka、RocketMQ、RabbitMQ、Pulsar、CMQ 五大产品,覆盖在线和离线场景,满足金融、互联网、教育、物流、能源等不同行业和场景的需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档