Handler(三) - Looper、Handler、Message三者关系

概述

通过下边的代码分析源码

        // 根据这个实例代码分析下边源码
        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 sThreadLocal = new ThreadLocal();

    /**
     *  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、Message三者关系)