Kotlin 协程 Flow 模块
1. 协程基础:挂起函数 suspend
suspend 关键字
kotlin
复制代码
// suspend 函数:可在特定点挂起协程,不会阻塞线程
suspend fun fetchUser(id: String): User {
// 网络请求会挂起,不会阻塞主线程
return api.getUser(id)
}
// 普通函数不能调用 suspend 函数
fun normalFunction() {
// fetchUser("1") // ❌ 编译错误
// 必须通过协程或 suspend 函数调用
}
// suspend 函数可调用 suspend 函数
suspend fun loadData(): List<User> {
val user = fetchUser("1") // ✅ OK
val posts = fetchPosts(user.id)
return combine(user, posts)
}
挂起原理
kotlin
复制代码
// Kotlin 协程编译器将 suspend 编译为状态机
// 挂起点:调用其他 suspend 函数、delay、await 等
// 伪代码展示挂起原理(实际编译器生成)
class loadDataCoroutine {
var label = 0
var result = emptyList<User>()
fun resume() {
when (label) {
0 -> {
label = 1
fetchUser("1").let { user ->
this.user = user
resume() // 回调继续
}
}
1 -> {
label = 2
// ...
}
}
}
}
launch / async 启动协程
kotlin
复制代码
import kotlinx.coroutines.*
// launch:启动不返回结果(fire-and-forget)
fun main() = runBlocking {
launch {
delay(1000)
println("Done 1")
}
launch {
delay(500)
println("Done 2")
}
println("Started")
// 输出:Started, Done 2, Done 1(500ms, 1000ms)
}
// async:启动并返回结果(用于并发)
suspend fun demo() = runBlocking {
val deferred = async {
delay(1000)
42
}
println("Waiting...")
val result = deferred.await() // 等待并获取结果
println("Result: $result") // Result: 42
}
// 并发执行
suspend fun parallelLoad() = runBlocking {
val start = System.currentTimeMillis()
val one = async { fetchOne() }
val two = async { fetchTwo() }
val three = async { fetchThree() }
val result = one.await() + two.await() + three.await()
// 三个请求并发执行,总耗时 ≈ 最慢的一个
println("Result: $result, took: ${System.currentTimeMillis() - start}ms")
}
2. 调度器 Dispatchers
三大调度器
kotlin
复制代码
import kotlinx.coroutines.Dispatchers
// Dispatchers.Main:主线程(UI 线程)
// Android:更新 UI
// Compose:Compose 线程
// 使用场景:UI 更新、LiveData.setValue、Compose state 更新
launch(Dispatchers.Main) {
textView.text = "Updated" // ✅ 主线程操作 UI
}
// Dispatchers.IO:I/O 操作(网络、磁盘、数据库)
// 适合:文件读写、网络请求、数据库操作
launch(Dispatchers.IO) {
val data = withContext(Dispatchers.IO) {
file.readText() // ✅ I/O 线程
}
// 自动切换回 Main 继续
withContext(Dispatchers.Main) {
textView.text = data // ✅ UI 更新
}
}
// Dispatchers.Default:CPU 密集型操作
// 适合:排序、JSON 解析、复杂计算
launch(Dispatchers.Default) {
val sorted = withContext(Dispatchers.Default) {
bigList.sorted() // ✅ CPU 密集型
}
}
调度器选择指南
调度器
线程池
使用场景
阻塞处理
Dispatchers.Main
主线程
UI 更新、Compose、LiveData
不阻塞
Dispatchers.IO
弹性线程池(最多 64)
网络、文件、数据库 I/O
可阻塞
Dispatchers.Default
CPU 核心数线程池(至少 2)
CPU 密集计算
可阻塞
withContext 切换上下文
kotlin
复制代码
// withContext:切换到指定调度器,执行完自动切回
suspend fun loadImage(): Bitmap {
return withContext(Dispatchers.IO) {
Glide.with(context).asBitmap().load(url).submit().get()
}
}
// ViewModel 标准写法
class MyViewModel : ViewModel() {
private val _data = MutableLiveData<String>()
val data: LiveData<String> = _data
fun load() {
viewModelScope.launch {
_data.value = "Loading..."
try {
val result = withContext(Dispatchers.IO) {
repository.fetchData()
}
_data.value = result
} catch (e: Exception) {
_data.value = "Error: ${e.message}"
}
}
}
}
// 连续切换
suspend fun process() {
withContext(Dispatchers.IO) { readFromDisk() }
.let { withContext(Dispatchers.Default) { parse(it) } }
.let { withContext(Dispatchers.Main) { updateUI(it) } }
}
调度器切换注意事项
kotlin
复制代码
// ❌ 错误:在 IO 操作后忘记切回 Main
launch(Dispatchers.IO) {
val data = api.getData()
// textView.text = data // ❌ 主线程更新,抛异常
}
// ✅ 正确:显式切换
launch(Dispatchers.IO) {
val data = api.getData()
launch(Dispatchers.Main) {
textView.text = data
}
}
// ✅ 正确:用 withContext
launch {
val data = withContext(Dispatchers.IO) { api.getData() }
textView.text = data // launch 已在 Main 启动
}
// ✅ 推荐:用 viewModelScope(自动在 Main 启动)
viewModelScope.launch {
val data = withContext(Dispatchers.IO) { api.getData() }
_data.value = data // Main 线程
}
3. 协程作用域 CoroutineScope
viewModelScope(ViewModel 官方推荐)
kotlin
复制代码
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
class MyViewModel : ViewModel() {
private val _items = MutableLiveData<List<Item>>()
val items: LiveData<List<Item>> = _items
fun loadItems() {
// viewModelScope 自动绑定 ViewModel 生命周期
viewModelScope.launch {
try {
_items.value = withContext(Dispatchers.IO) {
repository.getItems()
}
} catch (e: Exception) {
_items.value = emptyList()
}
}
}
// viewModelScope 会自动在 onCleared 时取消所有协程
}
// 生命周期绑定
// onCreate() -> 启动协程
// onCleared() -> 取消所有协程
// 配置变更(如旋转)-> viewModelScope 保持,自动取消旧协程
lifecycleScope(Activity/Fragment)
kotlin
复制代码
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.delay
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// lifecycleScope 绑定 Activity 生命周期
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
// 只在 STARTED 状态执行,STOPPED 时暂停,RESTARTED 时恢复
val data = repository.getData()
updateUI(data)
}
}
// launchWhenStarted:旧写法(不推荐,有泄漏风险)
lifecycleScope.launchWhenStarted {
// 只在 STARTED 时执行,STOPPED 时暂停
}
}
override fun onDestroy() {
super.onDestroy()
// lifecycleScope 自动取消,但 STOPPED 时已暂停
}
}
repeatOnLifecycle(官方推荐模式)
kotlin
复制代码
import androidx.lifecycle.repeatOnLifecycle
// repeatOnLifecycle:自动暂停/恢复
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
// STARTED 时开始执行
// STOPPED 时自动挂起(暂停)
// RESTARTED 时恢复执行
// DESTROYED 时取消(结束协程)
dataFlow.collect { data ->
updateUI(data)
}
}
}
// 配合 StateFlow / SharedFlow
lifecycleScope.launch {
viewModel.uiState
.repeatOnLifecycle(Lifecycle.State.STARTED)
.collect { state ->
render(state)
}
}
// 支持多个 Flow 同时收集
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
launch { viewModel.data.collect { /* */ } }
launch { viewModel.events.collect { /* */ } }
}
}
自定义 CoroutineScope
kotlin
复制代码
// 自定义 scope(通常配合 viewModelScope 使用)
class MyManager {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
fun doWork() {
scope.launch {
// 独立于 ViewModel 的协程
}
}
fun cleanup() {
scope.cancel()
}
}
// SupervisorJob:子协程失败不影响其他子协程
private val supervisor = SupervisorJob()
private val scope = CoroutineScope(supervisor + Dispatchers.Main)
scope.launch {
launch { throwException() } // 失败不影响其他
launch { anotherTask() } // 继续执行
}
// 注意: SupervisorJob 只对直接子协程有效
// 要让子协程失败不影响父协程,用 launch { ... }.launchIn(scope)
// 或使用 structured concurrency
全局作用域(慎用)
kotlin
复制代码
// GlobalScope:不推荐(无法取消,难测试)
GlobalScope.launch {
// 永远不会被自动取消
}
// GlobalScope 典型使用场景
// 库内部、后台任务、不与 UI 绑定的 long-running 任务
// Android 中很少使用
4. 通道 Channel
Channel 基础
kotlin
复制代码
import kotlinx.coroutines.channels.Channel
// Channel:协程间通信的管道(FIFO 队列)
// 类似于 BlockingQueue,但是非阻塞的
// 类型
val channel = Channel<Int>()
val channel2 = Channel<Int>(Channel.BUFFERED) // 带缓冲
val channel3 = Channel<Int>(Channel.RENDEZVOUS) // 零缓冲(默认)
// 发送和接收
suspend fun demo() {
val channel = Channel<String>()
launch {
channel.send("Hello")
channel.send("World")
channel.close() // 关闭 channel
}
// 接收
println(channel.receive()) // "Hello"
println(channel.receive()) // "World"
// channel.receive() // 挂起直到 close 或有新元素
}
// for 循环遍历
launch {
for (value in channel) {
println(value)
}
// 循环会在 channel.close() 且所有元素被消费后结束
}
Channel 类型
kotlin
复制代码
// 公平性:默认 Channel 是公平的(先到先服务)
// RENDEZVOUS(默认):发送和接收必须同时配对
// send() 会挂起直到有 receive() 等待
// receive() 会挂起直到有 send() 等待
// BUFFERED:固定容量缓冲
val bufferedChannel = Channel<Int>(capacity = 3)
bufferedChannel.send(1) // 不挂起直到 buffer 满
bufferedChannel.send(2)
bufferedChannel.send(3)
// bufferedChannel.send(4) // 挂起,直到 receive() 消费
// UNLIMITED:无限缓冲
val unlimited = Channel<Int>(Channel.UNLIMITED)
unlimited.send(1)
unlimited.send(100) // 永不挂起
// CONFLATED:超出容量时丢弃旧值
val conflated = Channel<Int>(Channel.CONFLATED)
conflated.send(1)
conflated.send(2) // 1 被丢弃
// 消费者只收到 2
Channel vs Flow
特性
Channel
Flow
用途
协程间通信
数据流处理
背压
支持
支持(缓冲 Flow)
关闭
必须手动 close
自动完成
语法
send/receive
emit/collect
热/冷
热(不订阅也发送)
冷(订阅时才发送)
Android
很少使用
大量使用
Channel 实战
kotlin
复制代码
// 场景:协程间事件通知
class EventBus {
private val _events = Channel<Event>(Channel.BUFFERED)
val events = _events.receiveAsFlow() // 转为 Flow 供外部收集
suspend fun send(event: Event) {
_events.send(event)
}
}
// 场景:并发任务结果收集
suspend fun collectResults(): List<Result> = coroutineScope {
val results = Channel<Result>()
// 并发执行多个任务
launch { results.send(processTask1()) }
launch { results.send(processTask2()) }
launch { results.send(processTask3()) }
// 收集所有结果
val collected = mutableListOf<Result>()
repeat(3) {
collected.add(results.receive())
}
collected
}
5. StateFlow / SharedFlow(热流)
StateFlow
kotlin
复制代码
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
// StateFlow:状态容器,始终持有最新值
// 新订阅者立即收到当前值
// 适合:UI 状态管理
class ViewModel {
private val _uiState = MutableStateFlow<UiState>(UiState.Idle)
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
fun load() {
_uiState.value = UiState.Loading // 更新状态
viewModelScope.launch {
try {
val data = repository.fetchData()
_uiState.value = UiState.Success(data)
} catch (e: Exception) {
_uiState.value = UiState.Error(e.message ?: "Error")
}
}
}
}
// Compose 中收集
@Composable
fun Screen(viewModel: MyViewModel) {
val uiState by viewModel.uiState.collectAsState()
when (uiState) {
is UiState.Idle -> Text("Idle")
is UiState.Loading -> CircularProgressIndicator()
is UiState.Success -> Text("Data: ${(uiState as UiState.Success).data}")
is UiState.Error -> Text("Error: ${(uiState as UiState.Error).message}")
}
}
SharedFlow
kotlin
复制代码
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
// SharedFlow:事件流,无状态
// 新订阅者不收旧值,只收订阅后发出的值
// 适合:一次性事件(导航、Toast、Snackbar)
class ViewModel {
private val _events = MutableSharedFlow<Event>()
val events: SharedFlow<Event> = _events.asSharedFlow()
fun onButtonClick() {
viewModelScope.launch {
_events.emit(Event.ShowToast("操作成功"))
}
}
}
// Activity/Fragment 收集事件
lifecycleScope.launch {
viewModel.events
.repeatOnLifecycle(Lifecycle.State.STARTED)
.collect { event ->
when (event) {
is Event.ShowToast -> showToast(event.message)
is Event.Navigate -> navigateTo(event.route)
}
}
}
StateFlow vs SharedFlow
特性
StateFlow
SharedFlow
初始值
必须有初始值
无初始值
新订阅者收到
最新值
订阅后的新值
replay
始终 replay 最新值
可配置 replay 数量
适用场景
UI 状态
一次性事件
状态保持
✅ 有
❌ 无
compose 支持
collectAsState()
collectAsState()(需 replay=1)
kotlin
复制代码
// SharedFlow 带 replay
val flow = MutableSharedFlow<String>(replay = 1)
// 订阅前发送的值会被新订阅者收到
flow.emit("Before subscribe")
flow.emit("After subscribe")
// 新订阅者收到 "After subscribe"(replay=1)
// SharedFlow 无 replay(默认 0)
val events = MutableSharedFlow<Event>()
// 新订阅者只收订阅后的事件
完整的事件+状态模式
kotlin
复制代码
// sealed class 状态定义
sealed class UiState<out T> {
object Idle : UiState<Nothing>()
object Loading : UiState<Nothing>()
data class Success<T>(val data: T) : UiState<T>()
data class Error(val message: String) : UiState<Nothing>()
}
// sealed class 事件定义
sealed class UiEvent {
data class ShowToast(val message: String) : UiEvent()
data class Navigate(val route: String) : UiEvent()
object NavigateBack : UiEvent()
}
// ViewModel
class MyViewModel(
private val repository: MyRepository
) : ViewModel() {
private val _uiState = MutableStateFlow<UiState<List<Item>>>(UiState.Idle)
val uiState: StateFlow<UiState<List<Item>>> = _uiState.asStateFlow()
private val _events = MutableSharedFlow<UiEvent>()
val events: SharedFlow<UiEvent> = _events.asSharedFlow()
fun load() {
viewModelScope.launch {
_uiState.value = UiState.Loading
runCatching {
repository.getItems()
}.onSuccess { items ->
_uiState.value = UiState.Success(items)
}.onFailure { e ->
_uiState.value = UiState.Error(e.message ?: "Unknown error")
}
}
}
fun onItemClick(item: Item) {
viewModelScope.launch {
_events.emit(UiEvent.Navigate("/detail/${item.id}"))
}
}
}
// Activity/Fragment 使用
class MyFragment : Fragment() {
private val viewModel: MyViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
launch {
viewModel.uiState.collect { state ->
render(state)
}
}
launch {
viewModel.events.collect { event ->
handleEvent(event)
}
}
}
}
}
}
6. 冷流与热流
冷流 Cold Flow
kotlin
复制代码
// Flow 默认是冷流:订阅时才生成数据
val coldFlow = flow {
println("Start generating")
for (i in 1..3) {
delay(100)
emit(i)
}
println("Done generating")
}
// 未订阅时不执行
// coldFlow // 不输出
// 订阅时才执行
coldFlow.collect { value ->
println("Received: $value")
}
// 输出:
// Start generating
// Received: 1
// Received: 2
// Received: 3
// Done generating
// 两个订阅者分别触发两次执行
coldFlow.collect { println("A: $it") } // 重新开始
coldFlow.collect { println("B: $it") } // 再次重新开始
// 输出两组独立的 "Start generating... Done generating"
热流 Hot Flow
kotlin
复制代码
// StateFlow / SharedFlow 是热流
// 无论有多少订阅者,源头只执行一次
val stateFlow = MutableStateFlow(0)
val sharedFlow = MutableSharedFlow<String>()
// 订阅者 1
launch {
stateFlow.collect { println("Subscriber 1: $it") }
}
// 订阅者 2
launch {
stateFlow.collect { println("Subscriber 2: $it") }
}
// 仅触发一次
stateFlow.value = 42
// Subscriber 1: 42
// Subscriber 2: 42
// SharedFlow 同理
launch {
sharedFlow.collect { println("Shared 1: $it") }
}
launch {
sharedFlow.collect { println("Shared 2: $it") }
}
sharedFlow.emit("Hello")
// Shared 1: Hello
// Shared 2: Hello
// 只触发一次 emit,两个订阅者都收到
冷流转热流
kotlin
复制代码
// shareIn:冷流转热流(SharedFlow)
val sourceFlow = flow {
emitAll(dataSource)
}.shareIn(
scope = viewModelScope, // 共享作用域
started = SharingStarted.WhileSubscribed(5000), // 订阅才启动
replay = 1 // 新订阅者重放最近 1 条
)
// stateIn:冷流转 StateFlow
val sourceFlow = flow {
emitAll(dataSource)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = UiState.Idle // StateFlow 必须有初始值
)
// started 参数说明
SharingStarted.WhileSubscribed(5000)
// 订阅者存在时保持活跃
// 最后订阅者消失后 5 秒停止(减少不必要的资源消耗)
// 适用于:网络请求流
SharingStarted.Eagerly
// 立即开始,无论订阅者数量
// 适用于:内存状态、配置
SharingStarted.Lazily
// 第一个订阅者出现才开始
// 永远不停止
// 适用于:一次性数据
典型使用场景
kotlin
复制代码
// 场景一:数据库变更流(热流)
class MyDatabase {
private val _dataChanges = MutableSharedFlow<Change>()
val dataChanges: SharedFlow<Change> = _asSharedFlow()
suspend fun onDataChanged(change: Change) {
_dataChanges.emit(change)
}
}
// 场景二:用户输入搜索(冷流 + debounce)
class SearchViewModel {
private val _searchQuery = MutableStateFlow("")
val searchQuery: StateFlow<String> = _searchQuery.asStateFlow()
val searchResults: StateFlow<List<Result>> = _searchQuery
.debounce(300) // 等待 300ms 无新输入才执行
.filter { it.length >= 2 }
.distinctUntilChanged() // 与上次相同跳过
.flatMapLatest { query -> // 取消旧请求
api.search(query)
}
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = emptyList()
)
fun onQueryChanged(query: String) {
_searchQuery.value = query
}
}
// 场景三:定时刷新(热流)
class DataRepository {
private val refreshTrigger = MutableSharedFlow<Unit>(replay = 1)
val data: Flow<List<Item>> = refreshTrigger
.onStart { emit(Unit) } // 立即触发一次
.flatMapLatest { api.getItems() }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
suspend fun refresh() {
refreshTrigger.emit(Unit)
}
}
7. Flow 常用操作符
转换与过滤
kotlin
复制代码
// map:转换
numbers.map { it * 2 }
// filter:过滤
numbers.filter { it > 3 }
// take:取前 N 个
numbers.take(3)
// drop:跳过前 N 个
numbers.drop(3)
// mapNotNull:转换并过滤 null
items.mapNotNull { it.parent }
// flatMapLatest:只保留最新请求的结果
searchQuery.flatMapLatest { query ->
api.search(query)
}
时间相关
kotlin
复制代码
// debounce:防抖(等待无新输入)
.editText
.textChanges()
.debounce(300)
// distinctUntilChanged:跳过连续重复
editText.textChanges()
.distinctUntilChanged()
// delayEvent:延迟(不是 debounce)
flow.delay(100)
// buffer:缓冲(不阻塞)
flow.buffer(100)
// timeout:超时
flow.timeout(3000)
异常处理
kotlin
复制代码
// catch:捕获异常(不中断流)
dataFlow
.catch { e -> emit(DefaultData) } // 发送默认值
.collect { /* */ }
// retry:重试
dataFlow
.retry(3) // 重试 3 次
.collect { /* */ }
// retryWhen:条件重试
dataFlow
.retryWhen { cause, attempt ->
cause is NetworkException && attempt < 3
}
Lifecycle 配合
kotlin
复制代码
// repeatOnLifecycle 已内置,Flow 无需额外处理
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
flow.collect { /* */ }
}
}
// onEach:在 collect 之前执行
flow
.onEach { state = it }
.onEach { updateUI(it) }
.launchIn(viewModelScope) // 直接在 scope 中运行
// launchIn:替代 collect 自动绑定 lifecycle
flow
.onEach { updateUI(it) }
.catch { showError(it) }
.launchIn(viewModelScope)
// ⚠️ 不推荐:生命周期管理不如 repeatOnLifecycle 清晰
8. Compose State 联动
StateFlow → Compose
kotlin
复制代码
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@Composable
fun UserScreen(viewModel: UserViewModel = viewModel()) {
// collectAsState:自动将 StateFlow 转为 Compose State
val uiState by viewModel.uiState.collectAsState()
// uiState 是 UiState 类型(不是 StateFlow)
// 当 viewModel.uiState.value 变化时,Composable 自动重组
when (val state = uiState) {
is UiState.Loading -> LoadingView()
is UiState.Success -> SuccessView(state.data)
is UiState.Error -> ErrorView(state.message)
}
}
// collectAsState 带生命周期(推荐)
val uiState by viewModel.uiState
.collectAsState(
initial = UiState.Idle,
context = rememberCoroutineScope().coroutineContext
)
MutableStateFlow vs MutableState
kotlin
复制代码
// MutableStateFlow(ViewModel 推荐)
class ViewModel {
private val _state = MutableStateFlow(UiState.Idle)
val state: StateFlow<UiState> = _state.asStateFlow()
}
// Compose 收集
@Composable
fun Screen(viewModel: MyViewModel) {
val state by viewModel.state.collectAsState()
}
// MutableState(Compose 内直接使用)
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("Count: $count")
}
}
// MutableStateFlow vs MutableState
// 场景一:ViewModel → UI(跨组件)→ MutableStateFlow
// 场景二:单个 Composable 内部 → MutableState
双向绑定
kotlin
复制代码
// ViewModel
class CounterViewModel : ViewModel() {
private val _count = MutableStateFlow(0)
val count: StateFlow<Int> = _count.asStateFlow()
fun increment() {
_count.value++
}
fun decrement() {
_count.value--
}
}
// Compose 单向数据流(推荐)
@Composable
fun CounterScreen(viewModel: CounterViewModel) {
val count by viewModel.count.collectAsState()
Column {
Text("Count: $count")
Row {
Button(onClick = { viewModel.decrement() }) {
Text("-")
}
Button(onClick = { viewModel.increment() }) {
Text("+")
}
}
}
}
// ViewModel 双向绑定(Android 原生风格)
// ViewModel 不适合双向绑定,Compose 单向数据流更清晰
快速对照表
概念
关键字
用途
挂起函数
suspend
可在协程中挂起,不阻塞线程
启动协程
launch
异步执行,不返回结果
启动协程
async
异步执行,返回 Deferred
主调度器
Dispatchers.Main
UI 线程、Android 主线程
IO 调度器
Dispatchers.IO
网络、文件、数据库
默认调度器
Dispatchers.Default
CPU 密集计算
作用域
viewModelScope
ViewModel 生命周期绑定
作用域
lifecycleScope
Activity/Fragment 生命周期
状态流
StateFlow
热流、状态管理、有初始值
共享流
SharedFlow
热流、事件通知、无初始值
通道
Channel
协程间通信、FIFO
冷流
flow { }
订阅时生成数据
热流
shareIn/stateIn
冷流转热流
重复生命
repeatOnLifecycle
自动暂停/恢复
记忆口诀 :
挂起不阻塞 → suspend
UI 更新 → Dispatchers.Main
IO 操作 → Dispatchers.IO
计算密集 → Dispatchers.Default
ViewModel 状态 → StateFlow
一次性事件 → SharedFlow
协程通信 → Channel
Flow 订阅 → repeatOnLifecycle + collect
Compose 状态 → collectAsState()