Skip to content

Main 与 Main.immediate ​

选择正确的 UI 调度器,是保证 Android 60fps (16ms/帧) 流畅度的关键细节。

致命差异:Queue vs Direct ​

  • Dispatchers.Main (标准):

    • 总是使用 Handler.post() 将任务扔进消息队列末尾。
    • 后果: 哪怕你已经在主线程,它也会强行排队,等待下一次 Looper 轮询。这至少会延迟一帧的执行,甚至引发掉帧。
  • Dispatchers.Main.immediate (推荐):

    • 智能判断: 先检查 Thread.currentThread() 是否是主线程。
    • 是: 直接执行 (Function Call),零延迟。
    • 否: 退化为 Handler.post()。

实战:Why it matters? ​

场景:RecyclerView 绑定数据 ​

kotlin
// 假设我们在 ViewModel 中加载数据
val data = repository.load()

// 切换回主线程赋值
withContext(Dispatchers.Main) { 
    // 这里会通过 Handler 发送消息
    // 如果消息队列繁忙(例如正在处理复杂的 Touch 事件),
    // UI 数据刷新会被延迟,用户会感到明显的“点击后迟钝”。
    adapter.submitList(data) 
}

withContext(Dispatchers.Main.immediate) {
    // 立即赋值!UI 瞬间响应。
    adapter.submitList(data)
}

场景:动画回调 ​

在 onAnimationUpdate 等高频回调中,由于已经处在主线程,使用 Main.immediate 能够确保每一帧的计算都能在 VSYNC 信号到来前完成,避免画面撕裂或卡顿。

最佳实践总结 ​

铁律

除非你有明确理由(比如故意想把任务推迟到下一个 Message Loop),否则所有涉及 UI 操作的场景请无脑使用 Dispatchers.Main.immediate。

Jetpack 的 lifecycleScope 和 viewModelScope 默认使用的就是 Main.immediate。