手写Handler总结

本文深入解析Android中Handler的内部工作原理,包括Looper、MessageQueue和Message的角色,以及如何在子线程中通过Handler发送消息到主线程。通过单元测试展示了如何创建Handler、发送消息及轮询处理消息的过程,验证了Handler机制的有效性。
摘要由CSDN通过智能技术生成

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是运行成功了的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值