为了账号安全,请及时绑定邮箱和手机立即绑定

手写Handler架构

标签:
Java

在了解Handler原理的同时可以翻看源码研究一下Handler架构,下面是本人手写的Handler架构

Message.java

public class Message {

    int what;
    Handler target;

}

Message类我写的很简单,源码中是有很多代码的,这里能够传递值的参数只有what。target对象主要是为了最终能够执行到handleMessage回调方法,具体作用可以在下文代码中可以看到。

MessageQueue.java

/**
 *  互斥队列的通用类
 */public class MessageQueue {    //声明阻塞队列
    private BlockingDeque blockingDeque = new LinkedBlockingDeque(50);    /**
     * 入队(生产者)
     * @param msg
     * @return
     */
    public void enqueueMessage(Message msg) {        if (msg.target == null) {            throw new IllegalArgumentException("Message must have a target.");
        }        try {
            blockingDeque.put(msg);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }    /**
     * 出队(消费者)
     * @return
     */
    public Message next() {
        Message msg = null;        try {
            msg = (Message) blockingDeque.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        }        return msg;
    }
}

MessageQueue类其实是最核心的地方了,这是一个消息队列,只有两种行文,出队和入队。并且,这是一个生产者、消费者设计模式。BlockingDeque是阻塞队列,在生产者、消费者设计模式中的运用比较常见。

Looper.java

public class Looper {    static MessageQueue mQueue;    private static ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();    private Looper() {
        mQueue = new MessageQueue();
    }    public static void prepare() {        if (sThreadLocal.get() != null) {            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }    public static Looper myLooper() {        return sThreadLocal.get();
    }    public static void loop(){        for(;;){
            Message msg = mQueue.next();            if(msg == null){                continue;
            }
            msg.target.dispatchMessage(msg);
        }
    }
}

Looper中含有一个消息队列,looper只负责一个任务,那就是无限遍历消息队列,如果队列中有消息,就从队首取出消息,传递给handleMessage回调方法。这里的dispatchMessage方法就是为了执行Handler的回调方法handleMessage。

Handler.java

public class Handler {

    private MessageQueue mQueue;    public Handler() {
        Looper.prepare();
        Looper looper = Looper.myLooper();
        mQueue = looper.mQueue;
    }    public void handleMessage(Message msg) {

    }    public void dispatchMessage(Message msg){
        handleMessage(msg);
    }    public void sendMessage(Message msg){
        MessageQueue queue = mQueue;        if (queue != null) {
            enqueueMessage(queue, msg);
        }
    }    private void enqueueMessage(MessageQueue mQueue, Message msg){
        msg.target = this;
        mQueue.enqueueMessage(msg);
    }
}

Handler负责将消息放进消息队列中,也就是所谓了入队了,sendMessage方法就是让消息入队。

Test.java

public class Test {    private static Handler handler = new Handler(){        @Override
        public void handleMessage(Message msg) {            super.handleMessage(msg);
            System.out.println(String.valueOf(msg.what));
        }
    };    public static void main(String[] args){        new Thread(new Runnable() {            @Override
            public void run() {                for(int i=0;i<100;i++){
                    Message message = new Message();
                    message.what = i;
                    handler.sendMessage(message);
                }
            }
        }).start();
        Looper.loop();
    }
}

Looper.loop()这个方法不能放入Activity的UI线程,否则会阻塞,这里我新建一个java的启动入口, 我们只需要执行main方法就可以了。

在底层中,ActivityThread是UI线程, Android的启动入口就是这个类的main方法,main方法中已经声明了Looper

Looper.prepareMainLooper();Looper.loop();

webp

图片.png



作者:NoBugException
链接:https://www.jianshu.com/p/92c8495c6ab1


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消