Android-Handler源码解析-使用

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退出。
}

说明:

  1. 子线程的使用为完整Looper使用(需要先prepare()准备后loop()轮询),主线程的因已在ActivityThread操作了所以此线程不再需要了。
  2. Looper相关介绍,请看Android-Handler源码解析-Looper
  3. 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)

说明:

  1. handler.obtainMessage()方法,使用Message.obtain()方法创建消息,并将其Messagetarget为当前Handler,以进行MessageHandler一对一绑定。如果需要使用原始的,请使用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())

说明:

  1. sendMessage()sendEmptyMessage()发送立即MessagesendMessageDelayed()sendEmptyMessageDelayed()发送延迟MessagesendMessageAtTime()sendEmptyMessageAtTime()发送指定时刻MessagesendMessageAtFrontOfQueue()发送排在消息队列的前面的Message
  2. 参数message同一个消息,不可以被发送多次,否则崩溃,推荐每次使用Message.obtain()获取新的Message
  3. 参数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)

说明:

  1. post()发送立即RunnablepostAtTime()发送延迟RunnablepostDelayed()发送指定时刻RunnablepostAtFrontOfQueue()发送排在消息队列的前面的Runnable
  2. 参数runnable同一个消息,可以被发送多次,可以配合参数token使用,这样能更精确的找到此runnable(删除用)。
  3. 参数token:为标记Runnable的标识。

处理Message

handler.sendMessage()时,才需要处理消息的接受,重写某HandlerhandleMessage()方法。

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)

说明:

  1. removeMessages():为删除此Message,参数whatMessage的标识,参数obj为辅助(删除同时满足whatobjMessage)。
  2. removeCallbacks():为删除此Runnable,参数runnableRunnable对象,参数token为辅助(删除同时满足runnabletokenRunnable)。
  3. removeCallbacksAndMessages():为删除此Message和此Runnable,参数tokenMessageRunnable的标识。参数token为删除所有objtokenRunnableMessage,如果token为空,所有RunnableMessage将被删除。
  4. 以上移除方法,全部只能移除此handler发出的MessageRunnable,不能移除其他handler发出的。
  5. 为了解决Handler引起的内存泄露问题,可以把Handler改为静态类,并使用WeakReference操作,并在ActiviyonDestroy()方法内调用如下:handler.removeCallbacksAndMessages(null);,此为在页面销毁的时移除此handler发出的所有MessageRunnable

判断

  • hasMessages()
  • hasCallbacks()
// hasMessages
handler.hasMessages(what)
handler.hasMessages(what, obj)
// hasCallbacks
handler.hasCallbacks(runnable)

说明:

  1. hasMessages():为判断是否有此Message,参数whatMessage的标识,参数obj为辅助(判断是否同时满足whatobjMessage)。
  2. hasCallbacks():为判断是否有此Runnable,参数runnableRunnable对象。

Looper

创建Looper

  • Looper.prepare()
  • Looper.prepareMainLooper()
Looper.prepare()
Looper.prepareMainLooper()

说明:

  1. 创建非主线程Looper只能通过Looper.prepare()方法创建,它是允许退出的。
  2. 创建主线程Looper,它是通过Android系统创建ActivityThreadmain方法内调用Looper.prepareMainLooper()创建),它是不允许退出的。
  3. Looper相关介绍,请看Android-Handler源码解析-Looper

获取Looper

  • handler.looper
  • Looper.myLooper()
  • Looper.getMainLooper()
val looper = handler.looper
val mainLooper = Looper.getMainLooper()
val currentLooper = Looper.myLooper()

说明:

  1. handler.looper:通过handler获取Looper
  2. Looper.myLooper():获取调用线程Looper,如果没有调用Looper.prepare(),则会为null
  3. Looper.getMainLooper():获取主线程Looper,已经维护好了,不会为null

轮询Looper

  • Looper.loop()
Looper.loop()

说明:

  1. Looper.loop():轮询当前Looper,方法调用之前一定要为当前线程准备Looper(调用Looper.prepare()),否则抛出异常
  2. Looper.loop()后面的代码不会执行到,除非Looper退出。

退出Looper

  • looper.quit()
  • looper.quitSafely()
looper.quit()
looper.quitSafely()

说明:

  1. looper.quit():不安全退出,它会删除消息队列所有消息。在不处理消息队列中的任何消息的情况下终止(此方法,可能不安全的,因为在looper终止之前可能无法传递一些消息)。
  2. looper.quitSafely():安全退出,它会删除消息队列所有未来(当前时刻以后)的消息处理消息队列中的已经到期所有消息不处理消息队列中的未来(当前时刻以后)到期所有消息的情况下终止
  3. looper被请求退出后,任何向队列发送消息的尝试都将失败。例如,Handler.sendMessage(Message)方法将返回false
  4. 主线程的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标识目标HandlerMessage内容。

MessageQueue

获取MessageQueue

  • looper.queue
  • Looper.myQueue()
val queue = looper.queue
val currentQueue = Looper.myQueue()

说明:

  1. looper.queue:通过looper获取MessageQueue
  2. Looper.myQueue():获取调用线程LooperMessageQueue,如果没有调用Looper.prepare(),则会抛出NullPointerException
  3. 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

说明:

  1. IdleHandler:为MessageQueue空闲(队列为空或者队列里的消息全部未到执行时刻)时进行执行,queueIdle()返回true将其保持,返回false将其删除
  2. queue.addIdleHandler()增加IdleHandler,如果没有进行移除(未调用removeIdleHandler()方法或queueIdle()方法返回true),则始终会在MessageQueue空闲时进行调用通知
  3. queue.removeIdleHandler()移除IdleHandler
  4. queue.isIdle:判断此MessageQueue,此时是否空闲状态。
  5. 可以使用此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)

说明:

  1. Message.obtain():获取Message,内部使用了复用
  2. Message相关介绍,请看Android-Handler源码解析-Message

回收Message

  • message.recycle()
message.recycle()

说明:

  1. message.recycle():回收Message,判断了Message如果处于使用状态,则抛出异常

异步Message

  • message.isAsynchronous()
  • message.setAsynchronous()
val asynchronous = message.isAsynchronous
message.isAsynchronous = true

说明:

  1. message.isAsynchronous()判断Message是否是异步的,如果是,则返回true
  2. message.setAsynchronous()设置Message是否是异步的,如果是,这意味着它不受Looper同步屏障的影响。
  3. 消息,分为同步消息异步消息默认同步消息
  4. 同步屏障,会屏障同步消息,确保只有异步消息执行,详细请看Android-Handler源码解析-MessageQueue-同步屏障
  5. 某些操作(比如视图失效)可能会在Looper消息队列中引入同步屏障,以阻止后续消息满足某些条件之前被传递。在view invalidation的情况下,调用android.view.View.invalidate后发布的消息会被一个同步屏障挂起,直到下一帧准备被绘制。同步屏障确保在恢复之前完全处理了无效请求。
  6. 异步消息免于同步屏障。它们通常表示中断输入事件其它必须独立处理的信号,即使其它工作已经暂停。
  7. 请注意,异步消息可能是按同步消息顺序交付的,尽管它们之间总是按顺序交付的。如果这些消息的相对顺序很重要,那么它们可能一开始就不应该是异步的,谨慎使用

其它

copyFrom()

message.copyFrom(otherMessage)

指定Message的属性,复制当前Message中。

sendToTarget()

message.sendToTarget()

将此Message发送到getTarget指定的Handler。如果未设置此字段,则抛出空指针异常。

四者关系

  1. Looper源码得知,一个线程对应一个Looper,一个Looper对应一个MessageQueue
  2. MessageQueue源码得知,一个MessageQueue对应多个Message
  3. Message源码得知,一个Message对应一个Handler
  4. Handler源码得知,多个Message可以共用一个Handler

总结:一个线程对应一个Looper,一个Looper对应一个MessageQueue,一个MessageQueue对应多个Message,一个Message对应一个Handler,但多个Message可以共用一个Handler

总结

以上就是Handler源码的使用部分,Handler其它源码部分看下面导航。欢迎大家点赞、收藏,以方便您后续查看,之后会出其它Android源码系列,请及时关注。如果你有什么问题,可以在评论区留言!

导航:

最后推荐一下我的网站,开发者(Developer)的博客(Blog): devblog.cn ,欢迎大家来体验!

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
京ICP备18058279号-1