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


相关推荐
遗悲风2 小时前
PHP伪协议全面解析:原理、常用场景、攻防实战与安全防护
android·安全·php
撩得Android一次心动2 小时前
Android Lifecycle 全面解析:掌握生命周期管理的艺术(源码篇)
android·lifecycle
stevenzqzq2 小时前
android fow 限流
android·限流·flow
冬奇Lab3 小时前
Android 15 显示子系统深度解析(二):图形缓冲区管理与HWC硬件合成
android
wings专栏3 小时前
Android触摸事件分发记录
android
aaajj4 小时前
【Android】声控拍照例子
android
stevenzqzq4 小时前
Android MVI 中 setState(reduce: State.() -> State) 设计说明文档
android·mvi框架
鸣弦artha4 小时前
Flutter框架跨平台鸿蒙开发——InheritedWidget基础使用-计数器案例
android·flutter·harmonyos
嵌入式-老费4 小时前
Android开发(开发板的三种操作系统)
android