produceState 是一个 Jetpack Compose 库中的函数,它用于将非 Compose 的异步或监听驱动的状态转换成 Compose 可以理解和响应的State。它特别有用于整合像 Flow、LiveData 或者 RxJava 这样的响应式流到 Compose UI 中。
produceState 函数返回一个 State 对象,并启动一个与 Composition 生命周期相关联的协程来更新这个 State 对象的值。
- 这个协程会在 Composable 进入Composition时启动,
- 并在 Composable 离开Composition时取消。
- 返回的
State是"合并"的,即多次设置相同的值不会触发重组。
使用 produceState 时,可以指定一个初始值和依赖项列表。当依赖项发生变化时,会自动取消当前的协程并启动一个新的协程。
@Composable
fun loadNetworkImage(
url: String,
imageRepository: ImageRepository = ImageRepository()
): State<Result<Image>> {
// Creates a State<T> with Result.Loading as initial value
// If either `url` or `imageRepository` changes, the running producer
// will cancel and will be re-launched with the new inputs.
return produceState<Result<Image>>(initialValue = Result.Loading, url, imageRepository) {
// In a coroutine, can make suspend calls
val image = imageRepository.load(url)
// Update State with either an Error or Success result.
// This will trigger a recomposition where this State is read
value = if (image == null) {
Result.Error
} else {
Result.Success(image)
}
}
}
class ImageRepository {
fun load(url: String): Image? { return null }
}
sealed class Result<out T> {
object Loading : Result<Nothing>()
object Error : Result<Nothing>()
class Success<T>(t: T?) : Result<T>()
}
在这个例子中,我们创建了一个带有初始值 Result.Loading 的 State<Result<Image>>。当 Composable loadNetworkImage 被加入到 Composition 中时,produceState 会启动一个协程,在该协程中我们调用 imageRepository.load(url) 来加载图片。
一旦图片加载完成,我们更新 State 的值。如果图片加载成功,我们设置值为 Result.Success(image);如果加载失败或图片为 null,我们设置值为 Result.Error。这个 State 的更新会触发使用该state的 Composable 重组。
produceState 在底层使用了其他的 Compose effect,它通过 remember { mutableStateOf(initialValue) } 来保持result变量,并在 LaunchedEffect 中触发producer块。当producer块中的 value 被更新时,result状态也会更新为新的值。