【发布时间】:2020-03-02 00:09:52
【问题描述】:
我在试图找出实现带有进度的 UseCase 的最佳方法时遇到了问题。我见过这样的例子:
Google I/O Android 应用 https://github.com/google/iosched/blob/master/shared/src/main/java/com/google/samples/apps/iosched/shared/domain/UseCase.kt
我不喜欢的有以下几点:
- 您将在 UI 中接收结果并在那里做出许多决定。
- 没有进展
我认为是对上述内容的升级:
Android 架构蓝图
他们正在使用协程,现在结果在 ViewModel 中,而且好多了。但同样:没有进展
我的问题是每个人都在使用 RxJava,因为其他人都在使用它。我看到很多人认为这是“在后台执行任务”。但这对我来说太多了。我不需要它。
我见过一些使用协程通道的例子,但它们真的很丑。
最近我偶然发现了 Roman Elizarov 的这篇文章:
https://medium.com/@elizarov/callbacks-and-kotlin-flows-2b53aa2525cf
我做了这样的事情:
class ProduceValueWithProgressUseCase @Inject constructor(
private val executor: Executor
) {
operator fun invoke(): Flow<Result<Int, Int>> {
return callbackFlow {
val callback = object : CallbackProgress {
override fun onProgress(result: Int) {
offer(Result.Loading(result))
}
override fun onSuccess(result: Int) {
offer(Result.Success(result))
close()
}
override fun onError(e: Exception) {
offer(Result.Error(e))
close()
}
}
val producer = ValueWithProgressProducer(callback)
executor.execute(producer)
awaitClose {}
}
}
}
这个想法是这个东西“生产者”使用回调来传播数据,就像大多数“旧”API一样。因此,我想通过流将代码传播到 ViewModel,而不是将回调放在那里。像这样:
viewModelScope.launch {
produceValueWithProgressUseCase().collect {
when (it) {
is Success -> view.showWithProgressResult(it.data)
is Loading -> view.updateProgress(it.progress)
else -> view.showError()
}
}
}
所以是的,基本上 Flows API 将为我完成这项工作。我什至创建了一个小应用程序来测试它,我只是在其中生成数字,它运行良好。我不喜欢它的是:
-
必须有太多的 ExperimentalCoroutinesApi 注释。例如这里(对不起格式):
@Suppress("NOTHING_TO_INLINE") @ExperimentalCoroutinesApi 公共内联乐趣回调流(@BuilderInference noinline 块:挂起 ProducerScope.() -> Unit): Flow = 通道流(块)
以上代码是文件的一部分:kotlinx.coroutines.flow.Builders.kt 来自版本:kotlinx-coroutines-core-1.3.2
- 在某些时候,我遇到了带有 @Preview 注释的内容。(老实说,不记得在哪里。这是我删除的内容。)
- 我也尝试了一点,看看测试将如何进行,但这并不简单。您可以在 Blueprinst 的代码中看到相同的内容。
- 我还将执行任务的代码和任务本身混合在一起。我的意思是callbackFlow()的用法。
所以最后我看到了一些看起来像是在尖叫着明年改变的事情。所以请发表你的想法。
【问题讨论】:
-
你能发布一些代码sn-ps吗? Flow 自 2019 年 8 月以来一直保持稳定。一些转换和终端运算符处于实验和预览阶段
-
@GiorgosNeokleous 你在这里。
-
确实
callbackFlow不稳定。但是你检查一下稳定的 API,我很确定你可以在没有callbackFlow的情况下实现你正在寻找的东西,而不是简单的旧Flows。不幸的是,我不在我的机器上玩一个例子 -
我留下了一个粗略的实现希望有帮助!
标签: android kotlin kotlin-coroutines clean-architecture