美文网首页android
Handler(三) - Looper、Handler、Mess

Handler(三) - Looper、Handler、Mess

作者: 世道无情 | 来源:发表于2019-01-27 16:28 被阅读170次

    概述

    通过下边的代码分析源码

            // 根据这个实例代码分析下边源码
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Looper.prepare();
                    // 子线程中创建 handler对象
                    handler2 = new Handler() ;
                    Looper.loop();
                }
            }).start();
    

    1. Looper源码


    Looper的构造方法:

        /**
         *  Looper 的构造方法
         */    
        private Looper(boolean quitAllowed) {
            // 在构造方法中 创建 MessageQueue消息队列对象
            mQueue = new MessageQueue(quitAllowed);
            mThread = Thread.currentThread();
        }
    
        // ThreadLocal作用:在 一个线程中存储一个变量,这里存储的是 looper对象
        static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    
        /**
         *  Looper.prepare()方法
         */ 
        private static void prepare(boolean quitAllowed) {
            // 从sThreadLocal对象中获取 looper对象,如果不为null,就抛异常,说明 Looper.prepare() 
            // 只能调用1次,保证1个线程中只有一个 looper对象
            if (sThreadLocal.get() != null) {
                throw new RuntimeException("Only one Looper may be created per thread");
            }
    
            // 第一次调用 Looper.prepare(),就把 looper对象存储到 sThreadLocal对象中
            sThreadLocal.set(new Looper(quitAllowed));
        }
    
        /**
         *  Looper.loop()方法
         */
        public static void loop() {
            // 从 ThreadLocal 中 获取looper对象
            final Looper me = myLooper();
    
            // 如果 looper 对象为空,就抛异常,因为 looper 对象是在 Looper.prepare() 方法中 
            // 通过 sThreadLocal.set(new Looper(quitAllowed)) 添加到 ThreadLocal 中的  ,
            // 先执行 Looper.prepare(),然后执行 Looper.loop()      
            if (me == null) {
                throw new RuntimeException("No Looper; Looper.prepare() wasn't 
                        called on this thread.");
            }
    
            // 从 looper 中 取出 消息队列 MessageQueue,因为 MessageQueue对象 是在 Looper的构造方法
            //  new出来的
            final MessageQueue queue = me.mQueue;
    
    
            // 从这里开始,就进入一个死循环
            for (;;) {
                // 从消息队列 中取出一条消息 msg
                Message msg = queue.next(); // might block
                // 如果 msg为null,消息队列进入阻塞状态
                if (msg == null) {
                    // No message indicates that the message queue is quitting.
                    return;
                }
    
                try {
                    // msg.target就是handler,如果 消息队列中有消息 msg,就把 msg交给 
                    // handler.dispatchMessage处理
                    msg.target.dispatchMessage(msg);
                } finally {
                    //...
                }
                // 释放消息占用的资源 
                msg.recycleUnchecked();
            }
        }
    
        /**
         * 从ThreadLocal中获取 looper,然后返回 looper对象
         */
        public static @Nullable Looper myLooper() {
            return sThreadLocal.get();
        }
    

    结论:

    1>:由下可知:一个线程只有1个looper对象;
    if (sThreadLocal.get() != null) {
          throw new RuntimeException("Only one Looper may be created per thread");
    }
    
    由下可知:一个looper对象 只有1个 消息队列MessageQueue
    private Looper(boolean quitAllowed) {
            // 在构造方法中 创建 MessageQueue消息队列对象
            mQueue = new MessageQueue(quitAllowed);
            mThread = Thread.currentThread();
        }
    
    2>:对于 loop() 方法:不断的从 消息队列MessageQueue 中取出 消息msg,如果msg为null,则消息队列阻塞;如果有消息msg就交给 handler.dispatchMessage(msg)处理;

    2. Handler源码


    首先看Handler的构造方法:

        public Handler() {
            this(null, false);
        }
    
    public Handler(Callback callback, boolean async) {
            // ... 省略一些代码
    
            // 从 ThreadLocal中获取之前存储的 looper对象
            mLooper = Looper.myLooper();
            if (mLooper == null) {
                throw new RuntimeException(
                    // 必须先调用 Looper.prepare(),然后才可以 在子线程中创建 handler对象,
                    // 就是最上边的实例代码写法,否则抛出下边异常
                    "Can't create handler inside thread that has not called Looper.prepare()");
            }
    
            // 从 looper中取出  消息队列 MessageQueue
            mQueue = mLooper.mQueue;
            mCallback = callback;
            mAsynchronous = async;
        }
    

    然后看发送消息方法 sendMessage():

        /**
         *  任何的发送消息方法最终都会调用到 下边的方法
         */
        public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
            // 获取消息队列 MessageQueue 
            MessageQueue queue = mQueue;
            if (queue == null) {
                RuntimeException e = new RuntimeException(
                        this + " sendMessageAtTime() called with no mQueue");
                Log.w("Looper", e.getMessage(), e);
                return false;
            }
            return enqueueMessage(queue, msg, uptimeMillis);
        }
    
        private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
            //  msg.target是handler
            msg.target = this;
            if (mAsynchronous) {
                msg.setAsynchronous(true);
            }
            // 最终会调用 MessageQueue 中的 enqueueMessage()方法,
            // 也就是说 handler发出的消息最终会保存到 消息队列中
            return queue.enqueueMessage(msg, uptimeMillis);
        }
    
       /**
         * 在 Handler 的 dispatchMessage中处理 从消息队列MessageQueue中取出的msg
         */
        public void dispatchMessage(Message msg) {
            if (msg.callback != null) {
                handleCallback(msg);
            } else {
                if (mCallback != null) {
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                // 这个是我们自己实现的 handleMessage()方法,用于更新UI
                handleMessage(msg);
            }
        }
    

    3. 总结


    1>:对于Looper.prepare():在ThreadLocal中 保存 一个looper, 在 looper中保存 一个MessageQueue对象,因为 Looper.prepare() 只能调用1次,所以 MessageQueue只有1个;
    2>:对于Looper.loop():会让当前线程进入一个死循环(for循环),不断的从MessageQueue中取消息,然后调用 msg.target.dispatchMessage(msg) 把消息给 handler.dispatchMessage(msg);
    3>:对于Handler的构造方法Handler(...):首先从 ThreadLocal中获取之前存储的 looper 对象, 然后从 looper中获取 消息队列MessageQueue;
    4>:对于 Handler的 sendMessage():把 msg 加入到 消息队列 MessageQueue;
    5>:对于 Handler的 handleMessage():更新UI;

    相关文章

      网友评论

        本文标题:Handler(三) - Looper、Handler、Mess

        本文链接:https://www.haomeiwen.com/subject/grtzkqtx.html