produceState的使用:

12 阅读3分钟

一、produceState 到底是什么?

一句话定义

produceState 是一个 Compose 内置的 Effect,用于在协程中异步生产数据,并自动将其转换为 State<T>,让 UI 可以直接观察使用。

它帮你做了三件事:

  1. 创建并管理一个 State 对象
  2. 提供一个协程作用域执行异步代码
  3. 自动绑定生命周期(退出组合自动取消协程,不会泄漏)

二、核心语法结构

kotlin

@Composable
fun <T> produceState(
    initialValue: T,                // 【必须】初始值
    key1: Any?,                     // 【可选】key,变化会重启协程
    ...                             // 最多支持 3 个 key
    block: suspend ProduceStateScope<T>.() -> Unit
): State<T>

内部核心:

  • initialValue:第一次重组时返回的值
  • key:key 变化 → 取消旧协程 → 启动新协程
  • value:特殊变量,赋值即可更新 State,触发 UI 重组
  • awaitDispose {} :清理资源(如反注册、关闭流)

三、最基础标准使用示例

kotlin

@Composable
fun UserInfoScreen(userId: String) {
    // 1. 定义:自动返回 State<User>
    val userState: State<User?> = produceState(
        initialValue = null,  // 初始状态
        key1 = userId         // userId 变化,重新获取数据
    ) {
        // 2. 协程作用域
        val user = api.getUserById(userId) // 网络请求
        value = user // 3. 赋值 -> 更新 State -> UI 刷新
    }

    // UI 直接使用
    Text(text = userState.value?.name ?: "加载中...")
}

四、produceState 核心特点(必背)

  1. 返回 State<T> ,可直接用于重组

  2. 内部是协程,支持 suspend 函数

  3. 自动管理生命周期

    • 进入组合:启动协程
    • 退出组合:取消协程
    • Key 变化:重启协程
  4. 无需手动创建 mutableStateOf

  5. 自带资源清理:awaitDispose

  6. 只能在 @Composable 函数中调用

五、最常用 4 大实战场景

场景 1:网络请求(一次性)

kotlin

@Composable
fun LoadData() {
    val dataState by produceState<Result<Data>>(Result.Loading, key1 = id) {
        value = try { Result.Success(api.fetch(id)) } 
        catch (e: Exception) { Result.Error(e) }
    }

    when (dataState) {
        is Result.Loading -> Loading()
        is Result.Success -> ShowData(dataState.data)
        is Result.Error -> ErrorView()
    }
}

场景 2:轮询 / 定时任务(你的录音振幅)

kotlin

@Composable
fun rememberAmplitudeState(recorder: AudioRecorder): State<Float> {
    return produceState(initialValue = 0f, key1 = recorder) {
        // 持续轮询
        while (recorder.isRecording) {
            delay(300) // 300ms 刷新
            val amp = recorder.currentRecordMaxAmplitude / 32767f
            value = amp.coerceIn(0f, 1f) // 更新振幅
        }
    }
}

场景 3:回调 / 订阅 / 监听 → 转 State

kotlin

@Composable
fun rememberLocationState(): State<Location> {
    return produceState(initialValue = Location.Default) {
        val callback = LocationCallback { location ->
            value = location // 监听 -> 自动更新 State
        }
        locationManager.register(callback)

        // 关键:清理
        awaitDispose {
            locationManager.unregister(callback)
        }
    }
}

场景 4:数据流(Flow)→ 转 State

kotlin

@Composable
fun observeDataFlow(): State<Data> {
    return produceState(initialValue = emptyData()) {
        dataFlow.collect { data ->
            value = data
        }
    }
}

六、重要 API:awaitDispose ()

作用:协程取消 /key 变化 / 组件销毁时,执行清理

kotlin

produceState(Unit) {
    val callback = MyListener { value = it }
    register(callback)

    // 必须释放的资源
    awaitDispose {
        unregister(callback)
    }
}

七、produceState 与 LaunchedEffect 区别(面试必考)

表格

特性produceStateLaunchedEffect
返回值返回 State<T>无返回值
作用异步数据 → UI 状态执行异步任务
状态管理自动创建、自动更新需手动维护 State
代码量极少较多
适用场景UI 展示的数据来源事件、动画、无状态任务

总结

  • 要数据给 UI 用 → produceState
  • 只执行任务,不要返回值 → LaunchedEffect

八、与其他 Effect 的关系

  • LaunchedEffect:做任务
  • produceState做任务 + 输出 State
  • SideEffect:同步副作用
  • DisposableEffect:注册 / 清理
  • rememberUpdatedState:保持值最新

九、使用注意事项(避坑)

  1. 必须提供 initialValue
  2. key 正确设置,避免不必要重启
  3. 循环必须配合条件,避免无限运行
  4. 敏感资源必须用 awaitDispose 释放
  5. 不要在内部更新外部 State(会导致混乱)

十、最终极简总结

produceState = 协程 + State + 生命周期管理

  • 异步数据变成Compose 可观察状态
  • 自动管理协程,安全不泄漏
  • 适合:网络、轮询、监听、订阅、数据流