Kotlin 1.9.10中StateFlow map扩展编译错误修复咨询
在Kotlin 1.9.10环境中,自定义的StateFlow.mapStateFlow扩展函数出现编译错误,代码如下:
/** * Like [Flow.map], but returns a [StateFlow] rather than a [Flow]. As a consequence, [transform] * cannot be a suspend function. */ fun <T, R> StateFlow<T>.mapStateFlow(transform: (T) -> R): StateFlow<R> = MapStateFlow(this, transform, this.map { transform(it) }) private class MapStateFlow<T, R>(private val inStateFlow: StateFlow<T>, private val transform: (T) -> R, private val outFlow: Flow<R>) : Flow<R> by outFlow, StateFlow<R> { override val value: R get() = transform(inStateFlow.value) override val replayCache: List<R> get() = listOf(value) }
编译错误提示:
Type of 'public open suspend fun collect(collector: FlowCollector): Unit defined in com.organum.playscore.utils.extensions.MapStateFlow' is not a subtype of overridden by delegation 'public abstract suspend fun collect(collector: FlowCollector): Nothing defined in kotlinx.coroutines.flow.StateFlow'
已知Flow的collect方法返回Unit,StateFlow的collect方法返回Nothing,但不清楚版本变更导致代码失效的原因,需要修复方案。
问题原因
在适配Kotlin 1.9.x的kotlinx.coroutines新版本中,StateFlow的collect方法签名被调整为返回Nothing——这是因为StateFlow的collect会永久挂起,不会正常返回。原代码通过Flow<R> by outFlow委托实现collect方法,而委托的Flow的collect返回Unit,与StateFlow要求的Nothing返回类型冲突,直接导致编译失败。
修复方案
移除委托逻辑,直接重写collect方法,确保返回类型符合StateFlow的要求:
/** * Like [Flow.map], but returns a [StateFlow] rather than a [Flow]. As a consequence, [transform] * cannot be a suspend function. */ fun <T, R> StateFlow<T>.mapStateFlow(transform: (T) -> R): StateFlow<R> = MapStateFlow(this, transform) private class MapStateFlow<T, R>( private val source: StateFlow<T>, private val transform: (T) -> R ) : StateFlow<R> { override val value: R get() = transform(source.value) override val replayCache: List<R> get() = listOf(value) override suspend fun collect(collector: FlowCollector<R>): Nothing { source.collect { value -> collector.emit(transform(value)) } } }
修复细节
- 去掉了原代码中冗余的
outFlow参数和Flow委托,直接在类中重写collect方法 - 重写的
collect方法调用源StateFlow的collect,在回调里完成值的转换并发射给收集器。由于源StateFlow的collect本身返回Nothing,当前方法自然满足返回类型要求 - 简化了类的构造逻辑,无需预先创建转换后的
Flow,直接在收集过程中处理转换逻辑
内容的提问来源于stack exchange,提问作者James Sutton

