Android消息机制原理,仿写Handler Looper源码解析跨线程通信原理--之仿写模拟Handler(四)

前篇总结:上一篇实现了用Looper管理消息队列和消息循环,但是消息的发送和消息处理都是在Looper中进行的。写一个子线程使用这样的Looper怎么才能获取到loop()死循环消息队列取出的消息呢?用回调!callBack!

第四节 仿写Handler来发送消息,实现回调接口,处理消息

Handler类的功能很简单:1.就是发送消息到本线程(Handler和Looper在同一个线程)的Looper对象的消息队列里。 2.实现消息回调方法处理消息。

public class TestThreadMsg5 {
    public static Handler mainHandler;

    public static void main(String[] args){
        Looper.prepare();

        mainHandler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                System.out.println("主线程:"+Thread.currentThread().getId()+"  收到消息:"+msg.obj);
                if (msg.what == 1){
                    System.out.println("主线程:"+Thread.currentThread().getId()+"  do work!");
                    System.out.println("");
                    System.out.println("");
                }
                return false;
            }
        });

        Thread1 t1 = new Thread1();
        t1.start();

        Looper.loop();//阻塞式,死循环遍历消息列表
    }

    /**
     * 模拟Handler,主要职责:
     *   1.把消息放入到线程对应的Looper对象的消息队列里
     *   2.处理消息
     * Handler就是一个线程处理消息的钩子或者叫句柄,一个线程可以有很多个Handler实例
     * 所以每个Message对象都有个target,指明消息对象由哪个Handler进行处理
     * 而每个线程只允许有一个Looper对象与之对应,只有一个Looper对象自然也就只有一个消息队列了。
     *
     */
    public static class Handler {
        Looper mLooper = null;
        LinkedTransferQueue mQueue = null;
        Callback mCallback = null;

        //回调接口
        public interface Callback {
            public boolean handleMessage(Message msg);
        }

        public Handler(Callback callback) {
            this.mLooper = Looper.myLooper();
            this.mQueue = mLooper.mQueue;
            this.mCallback = callback;
        }

        public void dispatchMessage(Message msg){
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
        }

        public final void sendMessage(Message msg){
            msg.target = this;
            mQueue.put(msg);
        }
    }

    /**
     * 消息实体类,主要职责:
     *  1.承载消息内容
     *  2.指定由谁来处理我(消息)
     */
    static class Message {
        public int what;
        public Object obj;
        public Handler target;//消息对应的Handler
    }

    /**
     * 模拟Looper,主要职责:
     *  1.创建管理消息队列
     *  2.不断死循环取出消息队列里的消息
     *  3.处理消息(后续交给Handler处理)
     *  说明:Looper用静态prepare()方法实例化自己,每个线程只能实例化一个Looper对象
     *  Looper的myLooper()方法,在哪个线程调用就返回哪个线程的Looper对象(通过ThreadLocal实现)
     */
    static class Looper{
        //ThreadLocal用于保存某个线程共享变量:对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量
        static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
        LinkedTransferQueue mQueue;//阻塞式消息队列,每一个线程对应一个消息队列

        private Looper(){
            this.mQueue = new LinkedTransferQueue();//初始化阻塞式消息队列
        }

        /**
         * 初始化Looper,并放到线程变量里,
         * 这里做了限制,每个线程只能有一个Looper对象,因为是死循环多个也无意义
         */
        public static void prepare() {
            if (sThreadLocal.get() != null) {
                throw new RuntimeException("Only one Looper may be created per thread");
            }
            sThreadLocal.set(new Looper());
        }

        /**
         * 从线程变量里取出,当前线程对应的Looper
         * @return
         */
        public static Looper myLooper() {
            return sThreadLocal.get();
        }

        /**
         * 取出当前线程里的Looperd对象开始死循环遍历消息队列
         */
        public static void loop(){
            final Looper me = myLooper();
            //模拟LOOP的循环方法
            for (;;) {
                Message msg = null;
                try {
                    msg = (Message) me.mQueue.take();
                    msg.target.dispatchMessage(msg);//交个Message指定的Handler去处理
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        public LinkedTransferQueue getQueue() {
            return mQueue;
        }
    }


    static class Thread1 extends Thread{
        @Override
        public void run() {
            super.run();
            for (;;) {
                try {
                    Message msg = new Message();
                    msg.what = 1;
                    msg.obj = "主线程去更新UI吧";
                    System.out.println("子线程:"+Thread.currentThread().getId()+"  发送消息:"+msg.obj);
                    mainHandler.sendMessage(msg);//向主线程的Looper的消息队列里添加消息
                    Thread.sleep(5000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

首先说明下:1.在一个线程中可以有很多个Handler实例。 2.在线程中new Handler时 Handler会从Looper的myLooper()方法拿到当前线程的Looper对象,也顺便拿到Looper的Message队列。

        Looper的loop()循环遍历出的消息怎么交给Handler处理的?答案就是消息实体类Message,Message中的target指定了该消息由哪个Handler对象处理。Looper调用Handler的dispatchMessage派送消息给Handler,Handler再通过回调给用户处理。

基本模拟了Android中的Handler、Looper线程通信,但是Android的MessageQueue不是用LinkedTransferQueue实现的,不过也是采用阻塞链表实现的有兴趣的可以看看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值