背景
1、在日常Android研发工作中,经常用到Handler,但对其原理不熟悉。
目的
理解Handler 的工作原理
知识说明
- polling:轮询
- idle:闲置
- Threshold:阈值
- Dispatch:分发
- Asynchronous:异步的
- synchronous:同步的
- arbitrary:随意的,随心所欲的
- allocate:分配
- assign:分配
方案
理解Handler 从以下几个问题出发:
- Handler 是怎么工作的?
- 一个线程中到底有多少个Looper对象?
- Handler 是怎么实现线程切换的?
为了解答以上问题,结合源代码进行分析。
1、Handler 是怎么工作的?
Handler 其实就是Android封装的一个线程唯一的任务排队消费的模型。
从大的视角来看,Handler提供了五类API:
- 将Message加入到消息队列(将Runnable加入队列其实就是加入Message),例如 sendEmptyMessage、post、postDelay
- 将Message从消息队列中移除,例如 removeMessages、removeCallbacks
- 任务执行时的回调,例如 handleMessage
- 获得当前线程的Looper对象,例如 getLooper
- 替换日志打印Printer,便于调试,例如 dump
从大的视角来看,MessageQueue 提供了五类API:
- 当前线程中的消息队列是否空闲,例如 isIdle
- 增加、移除IdleHandler , 例如addIdleHandler
- 判断当前Looper是否在轮询中,例如 isPolling
- 添加、移除消息屏障,例如 postSyncBarrier、removeSyncBarrier
Looper的API:
- 准备,例如prepare、prepareMainLooper
- 开始循环,loop
- 设置观察者,setObserver
- 获得Looper对象,myLooper
- 获取LooperQueue对象,myQueue
Looper职责:从队列中依次取出消息
MessageQueue职责:消息入队、出队操作,对消息进行管理
Handler:将消息加入、删除
一个线程只能有一个Looper,但可以有无数个Handler;
每个Message 都持有一个对应的Handler;
若使用post接口传入Runnable对象,则这个Runnable对象为Message对象的callback属性;
Message加入队列时,根据延迟时长大小,插入到消息队列中的不同节点;
技术注意点
- 使用 wait - notify 组合来让线程同步时,需用 try - finally 包裹任务,并在finally 中调用 notify ,避免线程卡死
- 使用 HandlerThread 时,需要在Looper准备好了之后再根据Looper新建Handler。