设为首页 加入收藏

TOP

深入理解 Handler 消息机制(五)
2019-09-06 00:27:03 】 浏览:146
Tags:深入 理解 Handler 消息 机制
e() 方法。这好像也是我们最常用的一种形式。

Message

之所以把 Message 放在最后说,因为我觉得对整个消息机制有了一个完整的深入认识之后,再来了解 Message 会更加深刻。首先来看一下它有哪些重要属性:

int what :消息标识
int arg1 : 可携带的 int 值
int arg2 : 可携带的 int 值
Object obj : 可携带内容
long when : 超时时间
Handler target : 处理消息的 Handler
Runnable callback : 通过 post() 发送的消息会有此参数

Message 有 public 修饰的构造函数,但是一般不建议直接通过构造函数来构建 Message,而是通过 Message.obtain() 来获取消息。

obtain()

public static Message obtain() {
    synchronized (sPoolSync) {
        if (sPool != null) {
            Message m = sPool;
            sPool = m.next;
            m.next = null;
            m.flags = 0; // clear in-use flag
            sPoolSize--;
            return m;
        }
    }
    return new Message();
}

sPool 是消息缓存池,链表结构,其最大容量 MAX_POOL_SIZE 为 50。obtain() 方法会直接从消息池中取消息,循环利用,节约资源。当消息池为空时,再去新建消息。

recycleUnchecked()

还记得 Looper.loop() 方法中最后会调用 msg.recycleUnchecked() 方法吗?这个方法会回收已经分发处理的消息,并放入缓存池中。

void recycleUnchecked() {
    // Mark the message as in use while it remains in the recycled object pool.
    // Clear out all other details.
    flags = FLAG_IN_USE;
    what = 0;
    arg1 = 0;
    arg2 = 0;
    obj = null;
    replyTo = null;
    sendingUid = -1;
    when = 0;
    target = null;
    callback = null;
    data = null;

    synchronized (sPoolSync) {
        if (sPoolSize < MAX_POOL_SIZE) {
            next = sPool;
            sPool = this;
            sPoolSize++;
        }
    }
}

总结

说到这里,Handler 消息机制就全部分析完了,相信大家也对整个机制了然于心了。

  • Handler 被用来发送消息,但并不是真正的自己去发送。它持有 MessageQueue 对象的引用,通过 MessageQueue 来将消息入队。
  • Handler 也持有 Looper 对象的引用,通过 Looper.loop() 方法让消息队列循环起来。
  • Looper 持有 MessageQueue 对象应用,在 loop() 方法中会调用 MessageQueue 的 next() 方法来不停的取消息。
  • loop() 方法中取出来的消息最后还是会调用 Handler 的 dispatchMessage() 方法来进行分发和处理。

最后,关于 Handler 一直有一个很有意思的面试题:

Looper.loop() 是死循环为什么不会卡死主线程 ?

看起来问的好像有点道理,实则不然。你仔细思考一下,loop() 方法的死循环和卡死主线程有任何直接关联吗?其实并没有。

回想一下我们经常在测试代码时候写的 main() 函数:

public static void main(){
    System.out.println("Hello World");
}

姑且就把这里当做主线程,它里面没有死循环,执行完就直接结束了,没有任何卡顿。但是问题是它就直接结束了啊。在一个 Android 应用的主线程上,你希望它直接就结束了吗?那肯定是不行的。所以这个死循环是必要的,保证程序可以一直运行下去。Android 是基于事件体系的,包括最基本的 Activity 的生命周期都是由事件触发的。主线程 Handler 必须保持永远可以相应消息和事件,程序才能正常运行。

另一方面,这并不是一个时时刻刻都在循环的死循环,当没有消息的时候,loop() 方法阻塞,并不会消耗大量 CPU 资源。

关于 Handler 就说到这里了。还记得文章说过线程的 Looper 对象是保存在 ThreadLocal 中的吗?下一篇文章就来说说 ThreadLocal 是如何保存 线程局部变量 的。

文章首发微信公众号: 秉心说 , 专注 Java 、 Android 原创知识分享,LeetCode 题解。

更多最新原创文章,扫码关注我吧!

首页 上一页 2 3 4 5 下一页 尾页 5/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇基于wanAndroid-项目实战 下一篇Android几种多渠道打包

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目