Android-Handler源码解析-使用
源码版本:
* Handler:SDK-35
* 更新时间:2025-3月导航:
Handler
创建Handler
主线程
// 主线程Handler
val handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
// 用来处理消息,有handler.sendMessage()时,需要实现此方法;只handler.post()时,不用实现此方法。
}
}
子线程
// 开启子线程
thread {
// 准备
Looper.prepare()
val threadHandler = object : Handler(Looper.myLooper()!!) {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
// 用来处理消息,有handler.sendMessage()时,需要实现此方法;只handler.post()时,不用实现此方法。
}
}
// 轮询
Looper.loop()
// 后面执行不了,除非Looper退出。
}
说明:
- 子线程的使用为完整的
Looper
使用(需要先prepare()
准备后loop()
轮询),主线程的因已在ActivityThread
操作了所以此线程不再需要了。Looper
相关介绍,请看Android-Handler源码解析-Looper。Handler
相关介绍,请看Android-Handler源码解析-Handler。
创建Message
- obtainMessage()
handler.obtainMessage()
handler.obtainMessage(what)
handler.obtainMessage(what, obj)
handler.obtainMessage(what, arg1, arg2)
handler.obtainMessage(what, arg1, arg2, obj)
说明:
handler.obtainMessage()
方法,使用Message.obtain()
方法创建消息,并将其Message
的target
为当前Handler
,以进行Message
和Handler
一对一绑定。如果需要使用原始的,请使用Message.obtain()
。
发送
send-Message
- sendMessage()
- sendEmptyMessage()
- sendMessageDelayed()
- sendEmptyMessageDelayed()
- sendMessageAtTime()
- sendEmptyMessageAtTime()
- sendMessageAtFrontOfQueue()
val what = 111
// sendMessage
handler.sendMessage(Message.obtain())
handler.sendEmptyMessage(what)
// sendMessageDelayed
handler.sendMessageDelayed(Message.obtain(), 2000)
handler.sendEmptyMessageDelayed(what, 2000)
// sendMessageAtTime
handler.sendMessageAtTime(Message.obtain(), SystemClock.uptimeMillis() + 2000)
handler.sendEmptyMessageAtTime(what, SystemClock.uptimeMillis() + 2000)
// sendMessageAtFrontOfQueue
handler.sendMessageAtFrontOfQueue(Message.obtain())
说明:
sendMessage()
、sendEmptyMessage()
为发送立即Message,sendMessageDelayed()
、sendEmptyMessageDelayed()
为发送延迟Message,sendMessageAtTime()
、sendEmptyMessageAtTime()
为发送指定时刻Message,sendMessageAtFrontOfQueue()
为发送排在消息队列的前面的Message。- 参数
message
:同一个消息,不可以被发送多次,否则崩溃,推荐每次使用Message.obtain()
获取新的Message
。- 参数
what
:为标记Message
的标识,用于接收处理消息时、删除消息时判断。
post-Runnable
- post()
- postAtTime()
- postDelayed()
- postAtFrontOfQueue()
// post
handler.post(runnable)
// postAtTime
handler.postAtTime(runnable, SystemClock.uptimeMillis() + 2000)
handler.postAtTime(runnable, token, SystemClock.uptimeMillis() + 2000)
// postDelayed
handler.postDelayed(runnable, 2000)
handler.postDelayed(runnable, token, 2000)
// postAtFrontOfQueue
handler.postAtFrontOfQueue(runnable)
说明:
post()
为发送立即Runnable,postAtTime()
为发送延迟Runnable,postDelayed()
为发送指定时刻Runnable,postAtFrontOfQueue()
为发送排在消息队列的前面的Runnable。- 参数
runnable
:同一个消息,可以被发送多次,可以配合参数token
使用,这样能更精确的找到此runnable
(删除用)。- 参数
token
:为标记Runnable
的标识。
处理Message
有handler.sendMessage()
时,才需要处理消息的接受,重写某Handler
的handleMessage()
方法。
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
if (msg.what == 111) {
// 是自己发的消息,处理。
}
}
移除
- removeMessages()
- removeCallbacks()
- removeCallbacksAndMessages()
// removeMessages
handler.removeMessages(what)
handler.removeMessages(what, obj)
// removeCallbacks
handler.removeCallbacks(runnable)
handler.removeCallbacks(runnable, token)
// removeCallbacksAndMessages
handler.removeCallbacksAndMessages(token)
说明:
removeMessages()
:为删除此Message
,参数what
为Message
的标识,参数obj
为辅助(删除同时满足what
和obj
的Message
)。removeCallbacks()
:为删除此Runnable
,参数runnable
为Runnable
对象,参数token
为辅助(删除同时满足runnable
和token
的Runnable
)。removeCallbacksAndMessages()
:为删除此Message
和此Runnable
,参数token
为Message
、Runnable
的标识。参数token
为删除所有obj
为token
的Runnable
和Message
,如果token
为空,所有Runnable
和Message
将被删除。- 以上移除方法,全部只能移除此
handler
发出的Message
、Runnable
,不能移除其他handler
发出的。- 为了解决
Handler
引起的内存泄露问题,可以把Handler
改为静态类,并使用WeakReference
操作,并在Activiy
的onDestroy()
方法内调用如下:handler.removeCallbacksAndMessages(null);
,此为在页面销毁的时移除此handler
发出的所有Message
、Runnable
。
判断
- hasMessages()
- hasCallbacks()
// hasMessages
handler.hasMessages(what)
handler.hasMessages(what, obj)
// hasCallbacks
handler.hasCallbacks(runnable)
说明:
hasMessages()
:为判断是否有此Message
,参数what
为Message
的标识,参数obj
为辅助(判断是否同时满足what
和obj
的Message
)。hasCallbacks()
:为判断是否有此Runnable
,参数runnable
为Runnable
对象。
Looper
创建Looper
- Looper.prepare()
- Looper.prepareMainLooper()
Looper.prepare()
Looper.prepareMainLooper()
说明:
- 创建–非主线程
Looper
,只能通过Looper.prepare()
方法创建,它是允许退出的。- 创建–主线程
Looper
,它是通过Android
系统创建(ActivityThread
的main
方法内调用Looper.prepareMainLooper()
创建),它是不允许退出的。Looper
相关介绍,请看Android-Handler源码解析-Looper。
获取Looper
- handler.looper
- Looper.myLooper()
- Looper.getMainLooper()
val looper = handler.looper
val mainLooper = Looper.getMainLooper()
val currentLooper = Looper.myLooper()
说明:
handler.looper
:通过handler
获取Looper
。Looper.myLooper()
:获取调用线程的Looper
,如果没有调用Looper.prepare()
,则会为null
。Looper.getMainLooper()
:获取主线程的Looper
,已经维护好了,不会为null
。
轮询Looper
- Looper.loop()
Looper.loop()
说明:
Looper.loop()
:轮询当前Looper
,方法调用之前一定要为当前线程准备Looper
(调用Looper.prepare()
),否则抛出异常。Looper.loop()
后面的代码不会执行到,除非Looper
退出。
退出Looper
- looper.quit()
- looper.quitSafely()
looper.quit()
looper.quitSafely()
说明:
looper.quit()
:不安全退出,它会删除消息队列中所有消息。在不处理消息队列中的任何消息的情况下终止(此方法,可能是不安全的,因为在looper
终止之前可能无法传递一些消息)。looper.quitSafely()
:安全退出,它会删除消息队列中所有未来(当前时刻以后)的消息。处理消息队列中的已经到期的所有消息,不处理消息队列中的未来(当前时刻以后)到期的所有消息的情况下终止。- 在
looper
被请求退出后,任何向队列发送消息的尝试都将失败。例如,Handler.sendMessage(Message)
方法将返回false
。- 主线程的
Looper
不允许退出,子线程的Looper
不用了一定要记得退出。
其它
isCurrentThread()
val currentThread = looper.isCurrentThread
判断looper
的线程是否是当前线程,如果是,则返回true
。可以通过此判断当前线程是否是主线程,代码如下:
val isMainThread = Looper.getMainLooper().isCurrentThread
setMessageLogging()
looper.setMessageLogging { x -> Log.e("Looper", "x=$x") }
设置此Looper
处理消息时消息的日志记录。如果启用,日志消息将在每次消息分发的开始和结束时写到printer
,标识目标Handler
和Message
内容。
MessageQueue
获取MessageQueue
- looper.queue
- Looper.myQueue()
val queue = looper.queue
val currentQueue = Looper.myQueue()
说明:
looper.queue
:通过looper
获取MessageQueue
。Looper.myQueue()
:获取调用线程的Looper
的MessageQueue
,如果没有调用Looper.prepare()
,则会抛出NullPointerException
。MessageQueue
相关介绍,请看Android-Handler源码解析-MessageQueue。
Idle
- queue.addIdleHandler()
- queue.removeIdleHandler()
- queue.isIdle
val idleHandler = object : IdleHandler {
override fun queueIdle(): Boolean {
return true
}
}
// 增加
queue.addIdleHandler(idleHandler)
// 移除
queue.removeIdleHandler(idleHandler)
// 判断
val idle = queue.isIdle
说明:
IdleHandler
:为MessageQueue
空闲(队列为空或者队列里的消息全部未到执行时刻)时进行执行,queueIdle()
返回true
将其保持,返回false
将其删除。queue.addIdleHandler()
:增加IdleHandler
,如果没有进行移除(未调用removeIdleHandler()
方法或queueIdle()
方法返回true
),则始终会在MessageQueue
空闲时进行调用通知。queue.removeIdleHandler()
:移除IdleHandler
。queue.isIdle
:判断此MessageQueue
,此时是否空闲状态。- 可以使用此
IdleHandler
,实现优先级最低执行功能,例如某个的初始化需要在主线程执行,但是你不想阻塞主线程,优先级很低,则可以使用此在所有操作空余后初始化。
Message
创建Message
- Message.obtain()
Message.obtain(message)
Message.obtain(handler)
Message.obtain(handler,runnable)
Message.obtain(handler,what)
Message.obtain(handler,what, obj)
Message.obtain(handler,what, arg1, arg2)
Message.obtain(handler,what, arg1, arg2, obj)
说明:
Message.obtain()
:获取Message
,内部使用了复用。Message
相关介绍,请看Android-Handler源码解析-Message。
回收Message
- message.recycle()
message.recycle()
说明:
message.recycle()
:回收Message
,判断了Message
如果处于使用状态,则抛出异常。
异步Message
- message.isAsynchronous()
- message.setAsynchronous()
val asynchronous = message.isAsynchronous
message.isAsynchronous = true
说明:
message.isAsynchronous()
:判断Message
是否是异步的,如果是,则返回true
。message.setAsynchronous()
:设置Message
是否是异步的,如果是,这意味着它不受Looper
同步屏障的影响。- 消息,分为同步消息和异步消息,默认为同步消息。
- 同步屏障,会屏障同步消息,确保只有异步消息执行,详细请看Android-Handler源码解析-MessageQueue-同步屏障。
- 某些操作(比如视图失效)可能会在
Looper
的消息队列中引入同步屏障,以阻止后续消息在满足某些条件之前被传递。在view invalidation
的情况下,调用android.view.View.invalidate
后发布的消息会被一个同步屏障挂起,直到下一帧准备被绘制。同步屏障确保在恢复之前完全处理了无效请求。- 异步消息免于同步屏障。它们通常表示中断、输入事件和其它必须独立处理的信号,即使其它工作已经暂停。
- 请注意,异步消息可能是按同步消息的顺序交付的,尽管它们之间总是按顺序交付的。如果这些消息的相对顺序很重要,那么它们可能一开始就不应该是异步的,谨慎使用。
其它
copyFrom()
message.copyFrom(otherMessage)
将指定Message
的属性,复制到当前Message
中。
sendToTarget()
message.sendToTarget()
将此Message
发送到getTarget
指定的Handler
。如果未设置此字段,则抛出空指针异常。
四者关系
- 从
Looper
源码得知,一个线程对应一个Looper
,一个Looper
对应一个MessageQueue
。 - 从
MessageQueue
源码得知,一个MessageQueue
对应多个Message
。 - 从
Message
源码得知,一个Message
对应一个Handler
。 - 从
Handler
源码得知,多个Message
可以共用一个Handler
。
总结:一个线程对应一个Looper
,一个Looper
对应一个MessageQueue
,一个MessageQueue
对应多个Message
,一个Message
对应一个Handler
,但多个Message
可以共用一个Handler
。
总结
以上就是Handler
源码的使用
部分,Handler
其它源码部分看下面导航。欢迎大家点赞、收藏,以方便您后续查看,之后会出其它Android
源码系列,请及时关注。如果你有什么问题,可以在评论区留言!
导航:
最后推荐一下我的网站,开发者(Developer
)的博客(Blog
): devblog.cn ,欢迎大家来体验!