Kotlin进阶-1-消息传递机制-Handler

目录

1、背景

2、简介

3、使用

4、源码详解

4.1、第一步:Looper.prepare()

4.2、第二步:new Handler()

4.3、第三步:Looper.loop()

4.4、第四步:发送消息

5、全部代码

5.1、Handler类

5.2、Looper类

5.3、Message类

5.4、MessageQueue类


1、背景

1、我们都知道Android只允许在主线程中进行UI的更新操作,那么为什么不允许在子线程中更新UI呢?

答:这是因为Android的UI空间是线程不安全的,如果多线程并发访问UI,可能导致UI控件处于一个不可预期的状态。

2、那么为什么不给UI控件添加锁机制呢?

答:首先加上锁会让UI的更新逻辑变得复杂;其次锁机制会降低更新UI的效率。

2、简介

稍微了解过Handler原理的人,都知道Handler的实现其实和 Message、MessageQueue、Looper这三个类共同完成的。

  • Message :信息对象的实体类;
  • MessageQueue:存储Message对象的类,内部使用单链表的信息存储多个Message对象。
  • Looper :会开启个死循环,不断地从MessageQueue中的单链表中遍历Message对象,然后将Message对象分发给Handler处理。
  • Handler:作用就是将Message对象放入MessageQueue的单链表中,然后处理从Looper获取到的Message对象。

3、使用

当我们在主线程使用Handler的时候,一般都直接new 一个Handler就可以正常使用了。但是正常启用一个Handler流程需要调用Looper的prepare()和loop()方法。如下的代码:

那么主线程中的Handler为什么不需要调用这两个方法呢?

答:这是因为在主线程,也就是ActivityThread线程中,提前为我们调用了这两个方法。

4、源码详解

接下来的内容,是我在源码的基础上,简化了代码,自己实现的简易版Handler,方法名与源码都是对应的。如果有兴趣看源码可以对照这看,这样理解起来比较容易。

4.1、第一步:Looper.prepare()

prepare()的源码很简单,他就是利用ThreadLocal将我们new出来的Looper对象保存到了当前的所在的线程中。

ThreadLocal.ThreadLocalMap内部其实是一个数组保存着Looper。ThreadLocalMap是自定义的哈希映射,仅适用于维护线程局部值。 没有操作导出到ThreadLocal类之外。 该类是包私有的,以允许声明Thread类中的字段。

这样在我们new Thread("handler线程:")线程就有了Looper对象。

4.2、第二步:new Handler()

new Handler() 的实现其实很简单,就是实现了Callback接口来为后面处理消息做准备,而这里同时保存了Looper中的MessageQueue对象,这个对象在Looper.prepare()的时候,会new出来。

注意:在我们new Handler()的时候,如果没有提前调用Looper.prepare()方法,会报异常。

4.3、第三步:Looper.loop()

Looper.loop()方法的作用就是开启一个死循环,不断地从MesssageQueue的单链表中遍历下一个Message对象,然后将这个Message对象发送给Handler来处理。

1、loop()中 首先通过ThreadLocal.get()来获取我们接受消息线程的Looper对象;

2、然后得到这个Looper对象中的MessageQueue对象;

3、然后用这个MessageQueue对象调用自身的next方法,遍历单链表中的Message对象;

4、将获取到的Message对象,传递给Handler的dispatchMessage()方法来处理。「Message.target保存着的就是发送这个Message的Handler对象,这个会在第四步说明」

5、这样我们的Message对象就回调回我们new Handler时候的 handleMessage()函数中了

4.4、第四步:Handler.sendMessage()

我们完成上面的三步之后,发现我们的Looper在不断地从一个空的MessageQueue的单链表中,遍历Message对象。

这时候,就需要我们来发送一条Message来让Handler处理。

1、我们new 一个名字叫“Message线程”的线程,然后在里边通过我们前面new 的Handler对象发送了一条消息。

2、sendMessage()方法最后会调用MessageQueue对象的enqueueMessage()方法,将我们的Message对象插入到单链表中

3、这样我们的Looper.loop()就能获取到Message对象,这样我们的Handler的handleMessage()就能回调到Message对象。

注意:下面白色框中,就是将Handler对象保存在Message中的步骤。

5、全部代码

github地址

运行代码: 

public class TestMyHandler {

    private static Handler mHandler;

    public static void main(String[] args) throws InterruptedException {
        initHandler();

        Thread.sleep(3000);

        sendMessage();

    }
    
    private static void initHandler() {
        new Thread("Handler线程") {
            @Override
            public void run() {
                super.run();

                Looper.prepare();

                mHandler = new Handler(new Handler.Callback() {
                    @Override
                    public boolean handleMessage(Message msg) {

                        if (msg.what == 1000) {
                            String result = (String) msg.obj;
                            showLog("---接受--->: " + result);
                        }
                        return false;
                    }
                }, false);

                Looper.loop();
            }
        }.start();

    }

    private static void showLog(String msg) {
        System.out.println(Thread.currentThread().getName() + ": " + msg);
    }

    private static void sendMessage() {

        new Thread("Message线程") {
            @Override
            public void run() {
                Message msg = new Message();
                msg.what = 1000;
                msg.obj = Thread.currentThread().getName() + ": 你好啊";
                Message msg1 = new Message();
                msg1.what = 1000;
                msg1.obj = Thread.currentThread().getName() + ": 你好啊1";

                mHandler.sendMessage(msg);
                mHandler.sendMessage(msg1);
            }
        }.start();

    }
}

//输出结果
Handler线程: ---接受--->: Message线程: 你好啊
Handler线程: ---接受--->: Message线程: 你好啊1

5.1、Handler类

public class Handler {

    private final MessageQueue mQueue;
    private final Callback mCallback;

    /**
     * Callback interface you can use when instantiating a Handler to avoid
     * having to implement your own subclass of Handler.
     */
    public interface Callback {
        boolean handleMessage(Message msg);
    }

    /**
     * Subclasses must implement this to receive messages.
     */
    public void handleMessage(Message msg) {
    }

    public Handler() {
        this(null, false);
    }

    public Handler(Callback callback, boolean async) {

        Looper mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException("Can't create handler inside thread "
                    + Thread.currentThread() + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
    }

    /**
     * 发送消息
     */
    public final boolean sendMessage(Message msg) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            return false;
        }
        return enqueueMessage(queue, msg);
    }

    private boolean enqueueMessage(MessageQueue queue, Message msg) {

        msg.target = this;

        return queue.enqueueMessage(msg, 0);
    }

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

    private static void handleCallback(Message message) {
        message.callback.run();
    }

}

5.2、Looper类

class Looper {

    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
    /**
     * 当前线程
     */
    private final Thread mThread;

    MessageQueue mQueue;

    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

    static void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(true));
    }

    static Looper myLooper() {
        return sThreadLocal.get();
    }

    static void loop() {

        Looper me = myLooper();

        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        MessageQueue queue = me.mQueue;

        for (;;) {
            Message msg = queue.next(); // might block

            if (msg == null) {
                return;
            }

            try {
                msg.target.dispatchMessage(msg);

            } catch (Exception e) {
                e.printStackTrace();
            }

            msg.recycleUnchecked();
        }
    }
}

5.3、Message类

public class Message {

    int what;

    Object obj;

    long when;

    Handler target;

    private boolean isUse;

    Runnable callback;
    /**
     * MessageQueue 以单链表的形式来存储Message对象
     */
    Message next;

    void markInUse() {
        isUse = true;
    }

    public Runnable getCallback() {
        return callback;
    }

    public Message setCallback(Runnable r) {
        callback = r;
        return this;
    }

    void recycleUnchecked() {
        what = 0;
        obj = null;
        when = 0;
        target = null;
        callback = null;
    }
}

5.4、MessageQueue类

class MessageQueue {

    private Message mMessages;

    MessageQueue(boolean quitAllowed) {
    }

    /**
     * 将Message 对象插入到单链表中
     */
    boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }

        synchronized (this) {

            msg.markInUse();
            msg.when = when;
            Message p = mMessages;

            /*
             * 1、下面的操作是为了将单链表中的所有Message按照 延迟发送的时间排序
             * 2、新添加的msg需要插入到单链表中合适的位置
             */
            if (p == null || when == 0 || when < p.when) {
                // 将这个msg放在单链表的头部
                msg.next = p;
                mMessages = msg;
            } else {
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

        }
        return true;
    }

    Message next() {

        for (;;) {
            synchronized (this) {
                Message prevMsg = null;
                Message msg = mMessages;
                /*
                 * 如果Message 没有target就抛弃这些Message
                 */
                if (msg != null && msg.target == null) {
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null);
                }

                if (msg != null) {

                    // Got a message.
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;
                    }
                    msg.next = null;
                    msg.markInUse();
                    return msg;
                }

            }
        }
    }

}
原创文章 120 获赞 34 访问量 28万+

猜你喜欢

转载自blog.csdn.net/qq_34589749/article/details/105585779