手撸一个Android经典线程通讯框架:Handler

源码 2024-9-2 13:11:24 86 0 来自 中国
媒介

2022年已过1/4,时间过的真是快。近些年大Android的发展也非常灵敏,尤其是依照MVVM大概MVI架构下,利用Jetpack + Kotlin + Corroutine + Flow的组合,大大提升了Android应用的开发服从。然而,雷同的服从的提升每每是通过层层封装,潜伏底层原理,简化调用,从而达到低沉开发的上手门槛目的的。作为一个有品位的开发者,又怎能满意于只相识上层的API调用。本文我们就来通过实例来试着聊一聊Android经典线程通讯框架Handler的根本原理。
目的

通过实现一个简朴的Handler框架,试图表明其底层的工作原理。
配景知识


  • 线程间通讯
    即差别线程之间交换信息,Java中常见的有:

    • Object
      wait(), notify()/notifyAll()
    • LockSupport
      park(), uppark()
    • Condition
      await(), signal()/signalAll()

  • Android的Handler工作原理
    简言之,重复实行“发送消息-分发消息-处理处罚消息”。
    更精确的题目形貌应该是:Android的基于Handler + Message + MessageQueue + Looper的消息机制是怎么工作的?
Handler借助handler#sendMessage(message)方法,把消息Message对象插入消息队列MessageQueue对象中,同时Looper对象循环往复地从MessageQueue对象中取下一个消息Message对象分发给Looper对象地点线程去处理处罚,云云循环往复。
留意: 同一个线程中,Looper和MessageQueue有且只有一个实例,能且只能在该线程内部实例化。Handler可有多个实例,可在任意线程内实例化,但前需包管实例化动作地点线程的Looper已被初始化。另外,也可以通过调用带Looper参数的Handler构造器实例化,以达到关联指定线程(Looper地点)的目的。
从上述形貌中,我们可以得出几个关键的点:
消息对象:生存消息的数据结构(会生存发送者的Handler对象引用)
发送消息:调用者通过Handler#sendMessage(message)发送消息(发到那边?缓存MessageQueue
缓存消息MessageQueue生存由外部发送来的消息(怎么生存?雷同单向链表结构)
读取消息:Looper#loop()内调用MessageQueue.next()读取消息(没消息了怎么办?壅闭)
分发消息:取到消息后,实行消息对象持有的Handler对象的Handler#dispatchMessage(message)方法。(运行在哪个线程?Looper对象地点的线程)
处理处罚消息:Handler#dispatchMessage(message)内再调用Handler#handleMessage(message)方法,后者便正是调用者常重写的方法。
循环往复:Looper#loop()内部是一个for(;;){...},不绝实行,提供循环往复的驱动力。
线程内Looper对象唯一性:依赖ThreadLocal包管每个线程内部Looper唯一,即只被实例化一次。
线程内MessageQueue对象唯一性:被Looper实例化并持有,间接包管了唯一性。

  • Android主线程Handler利用
应用启动时,ActivityThread.main(String[])内部会提前初始化Looper。故在主线程内部,可直接利用Handler的无参数构造器实例化。


  • Android子线程Handler利用
如上所述,子线程利用Handler必要先确保Looper已被初始化,但子线程默认是没有初始化Looper的,故需在子线程实行的一开始自动调用Looper.prepare()和Looper.loop()。以后则可如在主线程一般任意实例化Handler


  • Android的HandlerThread原理
即封装了HandlerThread子类。HandlerThread#start()被调用后,该线程内部会初始化Looper实例。其他线程可从该HandlerThread对象中取出Looper实例,并用它构造出新的Handler对象。以后其他线程可借助该Handler对象,调用Handler#sendMessage(message)给HandlerThread的线程发送消息。
实现

思绪

在相识了上述的Android的Handler工作原理后,自己实现一个简朴的消息框架就有方向了,无非就是办理上述中提到的“消息对象”,“发送消息”,“缓存消息”……关键点即可。
线程内Looper对象唯一性线程内MessageQueue对象唯一性读取消息是必要偏重思量的。
编码

Message
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 18:24, Processed in 0.158478 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表