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


相关推荐
故渊at3 小时前
系列三:组件化与模块化进阶 | 第11篇 组件化项目规范与问题根治:依赖、资源、Manifest 与混淆的全链路管控
android·架构·mvvm·模块化·组件化
故渊at3 小时前
系列二:MVVM 深度实战与项目重构 | 第7篇 LiveData & StateFlow 状态管理实战:从“粘包弹”到“丝滑流式”
android·重构
是阿建吖!3 小时前
【Linux】信号
android·linux·c语言·c++
alexhilton6 小时前
AppFunctions:让你的Android应用更容易被AI智能体发现
android·kotlin·android jetpack
qq3621967056 小时前
APK文件签名校验教程:验证APK真伪的完整方法
android·智能手机
赏金术士6 小时前
Android 组件化概念和特征
android·kotlin·组件化
2501_9159090612 小时前
深入解析Mock.js:功能、应用及实战案例,提升前端开发效率
android·ios·小程序·https·uni-app·iphone·webview
流星白龙13 小时前
【MySQL高阶】21.撤销表空间,撤销日志
android·mysql·adb
我命由我1234514 小时前
Android 开发,FragmentPagerAdapter 的 isViewFromObject 方法问题
android·java-ee·kotlin·android studio·android jetpack·android-studio·android runtime