Android 协程 Channel 菜鸟教程


Android 协程 Channel 菜鸟教程(从 0 到能用)

0️⃣ Channel 是什么?(一句话先懂)

Channel 就是协程里的"消息队列 / 管道"

  • 一边 send(发送)
  • 一边 receive(接收)
  • 消息 按顺序 传递
  • 每条消息 只会被消费一次

1️⃣ 为什么 Android 需要 Channel?

在 Android 里,我们经常遇到这些场景:

  • 按钮点击
  • 列表 item 点击
  • 下拉刷新
  • 重试按钮

这些都有一个共同点:

它们是"事件",不是"状态"

类型 特点
状态(State) 可重复、可恢复
事件(Event) 一次性、不可回放

👉 Channel 非常适合装"事件"


2️⃣ Channel vs 你熟的东西

对比 SharedFlow / StateFlow

工具 适合
StateFlow UI 状态
SharedFlow 广播事件
Channel 单次事件 / 指令

3️⃣ 第一个最简单的 Channel 示例

3.1 创建 Channel

kotlin 复制代码
val channel = Channel<String>()

3.2 发送消息

kotlin 复制代码
launch {
    channel.send("Hello")
}

3.3 接收消息

kotlin 复制代码
launch {
    val msg = channel.receive()
    println(msg)
}

输出:

复制代码
Hello

4️⃣ Channel 是"挂起"的(很重要)

send / receive 都是 suspend

kotlin 复制代码
channel.send("hi")     // 可能挂起
channel.receive()      // 可能挂起

所以:

必须在协程里用


5️⃣ Channel 的几种常见容量(重点)

5.1 默认(RENDEZVOUS)

kotlin 复制代码
Channel()
  • 没缓冲
  • send 和 receive 必须"同时在场"
  • 不常用在 UI

5.2 BUFFERED(推荐)

kotlin 复制代码
Channel(Channel.BUFFERED)
  • 有默认缓冲
  • 适合大多数场景

5.3 UNLIMITED(谨慎)

kotlin 复制代码
Channel(Channel.UNLIMITED)
  • 无限缓冲
  • 永远不会阻塞 send
  • ❗可能内存泄漏

5.4 指定容量

kotlin 复制代码
Channel(capacity = 64)

6️⃣ Android 中的典型用法(重点)

ViewModel 接收 UI 事件

6.1 定义 Intent
kotlin 复制代码
sealed interface UiIntent {
    object LoadData : UiIntent
    data class ClickItem(val id: String) : UiIntent
}

6.2 定义 Channel
kotlin 复制代码
private val intentChannel = Channel<UiIntent>(Channel.BUFFERED)

6.3 UI 发送 Intent
kotlin 复制代码
viewModelScope.launch {
    intentChannel.send(UiIntent.LoadData)
}

6.4 ViewModel 处理 Intent
kotlin 复制代码
init {
    viewModelScope.launch {
        intentChannel.consumeAsFlow().collect {
            handleIntent(it)
        }
    }
}

7️⃣ 为什么用 consumeAsFlow()

kotlin 复制代码
intentChannel.consumeAsFlow().collect { ... }

因为:

  • Flow 更好写
  • 支持操作符
  • 自动处理取消

👉 Channel + Flow = 实战标配


8️⃣ Channel 和 Flow 的核心区别

特点 Channel Flow
是否冷流
是否缓存 可选 可选
是否一次性
是否广播

9️⃣ 常见错误(菜鸟最容易踩)

❌ 错误 1:用 Channel 装状态

kotlin 复制代码
Channel<State> // ❌

❌ 错误 2:用 UNLIMITED 不加限制

kotlin 复制代码
Channel(Channel.UNLIMITED) // ❌ 滥用

❌ 错误 3:在 UI 线程直接 receive

kotlin 复制代码
channel.receive() // ❌ 会卡死

🔟 Channel 什么时候不用?

  • 需要 多观察者SharedFlow
  • 需要 保存最后状态StateFlow
  • 只是一次简单回调 → 普通函数

11️⃣ 一句话速记(给菜鸟的)

Channel = 协程里的事件队列
Flow = 数据流
StateFlow = UI 状态


12️⃣ 你现在可以这样用(推荐模板)

kotlin 复制代码
private val intentChannel = Channel<UiIntent>(Channel.BUFFERED)

fun sendIntent(intent: UiIntent) {
    viewModelScope.launch {
        intentChannel.send(intent)
    }
}

init {
    viewModelScope.launch {
        intentChannel.consumeAsFlow().collect {
            handleIntent(it)
        }
    }
}

13️⃣ 总结一句话(最终记住这个)

Channel 是 Android 中处理"一次性 UI 事件"的最简单、最安全的协程工具。


相关推荐
Zhu7584 小时前
在k8s集群部署MySQL单实例,支持多个主流发行版
android·mysql·kubernetes
AFinalStone7 小时前
Android 7系统异常问题排查(四)Framework层(上)—System Server Watchdog
android·系统异常
宝杰X78 小时前
Android Room3 多平台数据库
android·数据库
huibin14785236911 小时前
热缓解学习记录
android·学习
小田的博客14 小时前
SAP MM 供应商银行主数据更新报错!message R1228!
android·java·服务器
一笑的小酒馆15 小时前
Android智能猫砂盆视频加载慢卡顿问题分析
android
只会cv的小前端17 小时前
七巧低代码服务端脚本使用方法
android·低代码·rxjava
17 小时前
Android 自定义 View 实战:从零打造工业级全向摇杆控件(OmniJoystickView)
android·kotlin·自定义view·摇杆控件
雨白17 小时前
深入理解 Kotlin 协程 (十一):以逸待劳,探秘 select 多路复用与并发安全策略
android·kotlin
hunterandroid19 小时前
[Android 从零到一] Android 深度链接与 App Links:从 URI Scheme 到可验证的应用跳转
android