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 事件"的最简单、最安全的协程工具。