《Android内核剖析》笔记 第2章 Java基础&异步消息处理模型(1)

  1. 一个处于无限循环的线程,循环体中从消息队列中取消息,并回调相应的消息处理函数;

  2. 其他外部线程可以向该队列发送消息,消息队列本身要线程安全;

  3. Android系统中异步消息处理实现原理

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 核心组件包括Handler、MessageQueue/Message、Looper;

  2. 理解线程局部变量ThreadLocal,其作用域为特定线程内,他在java多线程开发中被广泛用于数据共享和信息传递;

  3. 循环体Looper

  4. 若要想把一个普通线程变成异步消息处理线程,需要在Thread的run()方法中先调用Looper.prepare(),创建好一个消息队列MessageQueue,然后调用Looper.loop进入无限循环;

  5. loop无限循环中会调用MessageQueue.next()获取消息,若队列为空,则此时线程被挂起,处于wait状态;

若有消息,则取出,并回调msg.target.dispatchMessage()完成消息分发,msg.target指的是发送该msg的handler,而消息处理的具体业务逻辑在handler.handleMessage()中实现;

  1. Message被处理完成后需要执行msg.recycle()进行回收,因为Message对象是使用数据池进行复用的,在新建消息时通过handler.obtainMessage()获取,而不是new一个;

  2. 消息队列MessageQueue

  3. 队列的底层数据结构为链表,每个Message对象中包含一个next变量;该队列的具体实现是在native C中完成的,不知道为啥不直接在java中完成?莫非一个小小的队列性能都能差别这么大?

  4. 核心方法为取出和发布消息,分别为next()、enqueueMessage();

  5. next()方法执行细节

  6. 调用native方法 nativePollOnce(int ptr, int timeoutMillis);

第一个参数ptr实际上是一个C实现中的NativeMessageQueue数据对象,在执行时会被强制转换,该技巧在之前的JNI环节中C代码中如何使用持久对象有说明;

若队列中没有消息,则将当前线程挂起至wait状态,当enqueueMessage()方法被调用时会被唤醒;

若队列中有消息,则取出来赋值给当前java对象中的mMessages变量;

  1. 对取出的消息判断是否到了指定的执行时间,若到了则直接返回该Message;若未到执行时间则尝试取下一条消息;

注意:这部分代码需要和enqueueMessage()方法中的发送消息都保持线程安全,即使用相同的同步锁,避免消息队列出现数据不一致;

  1. 若队列中取出的消息未到执行时间或没有消息,则判断当前 mPendingIdleHandlers是否有注册空闲回调函数;若有,顺序执行注册过的函数列表;

  2. enqueueMessage()方法执行细节

  3. 当前待发送消息与当前对象中的Message具体执行时间做比较,将当前待发送消息插入到正确的队列位置中,确保消息在队列中是按照执行时间顺序排列的;

注意:这点在原书中并未说明,但却是MessageQueue的设计核心,因为直接关系到消息读取时的效率;

  1. 将待发送消息赋值给mMessages变量;

  2. 调用 nativeWake(int ptr);函数,将mMessages消息保存到C代码中的消息队列中,同时判断当前消息线程是否处于wait状态,是则唤醒;

  3. 以上涉及到的与native部分代码联动细节待深究;

  4. 业务逻辑代码继承Handler,开发者只需要和Handler打交道即可,无需知道Looper/MessageQueue;

  5. 重载 handleMessage()方法,实现消息处理的具体业务逻辑;

如果你不喜欢继承Handler,那你可以选择实现Handler.Callback这个接口,里面的方法名完全一样;

  1. 通过 handler.obtainMessage();生成消息;

  2. 发送时执行 handler.sendXXX系列方法、或postXXX系列方法;

  3. Handler.dispatchMessage()方法代码解析:

01public void dispatchMessage(Message msg) {
02        if (msg.callback != null) { //此处的callback其实就是附着在Message中的一个Runnable,消息一般为post系列方法发送
03            handleCallback(msg); //其实等同于 message.callback.run();
04        else {
05            if (mCallback != null) { //此处的callback是实现Handler.Callback接口的实例对象
06                if (mCallback.handleMessage(msg)) { //调用Handler.Callback接口中的方法
07                    return;
08                }
09            }
10            handleMessage(msg); //调用继承于Handler、重载过的handleMessage方法;
11        }

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618165277)

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值