栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

手写Handler总结

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

手写Handler总结

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 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;


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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/324828.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号