本天才带你飞,Handler之Loop消息泵机制你了解多少?

发布于:2023-01-11 ⋅ 阅读:(470) ⋅ 点赞:(0)

定义

Looper和MessageQueue的消息就像水泵和井(里边装的是水)的关系一样,我们有了消息(水),但是为了把水从井中抽取出来(循环起来),我们得有一个水泵作为动力,这个动力就是Looper。

如果我们在一个线程中调用Looper.prepare()...Looper.loop(),那么你的线程就成功升级为了一个Looper线程,这意味着你的线程有了一个消息泵(Looper)和一个消息队列(MessageQueue),此时你就可以调用Handler来进行线程间的通信了。
在这里插入图片描述

理解

我们应用的UI线程也就是主线程,在应用启动的时候,系统会自动初始化一个Looper,也就是说,我们的UI线程默认是Looper线程。这也就是为什么主线程中直接调用Handler没什么事,但是再子线程中创建Handler需要哦手动调用Looper.prepare()...Looper.loop()的和原因。

Android消息机制中,Looper处于核心地位,它类似于一个消息泵,不断从MessageQueue中读取数据,然后分发给Handler去处理。

二、Looper源码阅读:

上述子线程中调用了Looper.prepare()和Looper.loop()到底做了什么事情?

1、先看prepare()方法:
    public static void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }

prepare是一个静态方法,那就意味着可以直接通过类名访问,这个方法只做了一件事,就是创建一个Looper对象,把这个对象放到sThreadLocal中。在创建之前会判断sThreadLocal是否为空,即保证当前只有一个Looper对象。

2、loop方法:
public static void loop() {
 while (true) {
            Message msg = queue.next(); // might block
            if (msg != null) {
                if (msg.target == null) {
                    // No target is a magic identifier for the quit message.
                    return;
                }
msg.target.dispatchMessage(msg);
msg.recycle();
}
}

上述方法只截取了部分,可见也是一个静态方法,做的事情也很简单,很单调:不停的检查MessageQueue,拿到Message,根据Message的target将消息分发给Handler,分发完成之后回收消息;

总之,handler的线程就是提供下handler这个实例变量而已,而真正循环处理消息的线程是looper所在的线程了。

这就是Handler的Loop消息泵机制,一篇简单的解析。你是否能理解呢?更多有关framework以及它的Handler学习,可点击前往获取《Framework》《Handler》学习手册。由一位腾讯Android架构师整理合成,需要可上方粗体字获取!
在这里插入图片描述

总结:

Thread和Looper是一一对应关系。
Thread和MessageQueue也是是一一对应关系。
俗一点说:一个Thread只有一个Looper对象,一个MessageQueue对象;
Looper分发消息是阻塞式的(might block),即一个消息分发完成之后才会处理下一个消息。
“Looper就是一个While循环,不停的从MessageQueue读取Message并分发给Handler处理,而调用Looper.loop()启动了循环”。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到