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


相关推荐
alexhilton5 小时前
MVI模式的完整历史、误解和现代Android范式
android·kotlin·android jetpack
心中有国也有家11 小时前
AtomGit Flutter 鸿蒙客户端:Canvas 绘制进阶-路径、渐变与混合模式
android·javascript·flutter·华为·harmonyos
hunterandroid12 小时前
WorkManager 可靠性实战:唯一任务、重试与幂等设计
android·前端
程序员老刘12 小时前
Android 17的10个AI功能,国内用户真正能用的有几个?
android·flutter·ai编程
花开彼岸天~13 小时前
鸿蒙应用开发实战【94】— 实战多卡号场景管理最佳实践
android·华为·harmonyos·鸿蒙系统
用户416596736935513 小时前
视频源文件音频轨异常分析记录
android
我命由我1234514 小时前
集成 mupdf-android 的示例做为模块使用报错,程序包android.support.v4.view不存在
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
雨白16 小时前
嵌套 ScrollView 滑动冲突实战:实现内部优先滚动
android
阿pin16 小时前
Android随笔-IntentService详解(了解)
android·intentservice
海天鹰16 小时前
content://com.android.externalstorage.documents/document/primary%3A
android