我想将两个不同的函数合并到一个方法中:
接口(interface)(存储库):
suspend fun doSomeAction(id: String): Response
fun subscribeToResultFromAction(id: String): Flow<SomeResult>
今天我的实现可以工作,但我不喜欢:
override fun execute(id: String): Flow<Response> {
CoroutineScope(dispatcher).launch {
repository.doSomeAction(id)
}
return repository.subscribeToResultFromAction(id).map { action ->
when (action.name) {
"NameA" -> Response(action.id, ....)
"NameB" -> Response(action.id, ....)
else -> {
Timber.e("Unexpected action!")
throw java.lang.Exception()
}
}
}
}
但我想先设置订阅,这样我就不会错过 doSomeAction(...) 的任何操作。它可以在订阅准备好之前开始生成我想要订阅的结果,这就是我想首先设置订阅的原因。如果该挂起功能失败,则不会有任何内容可供订阅。那么我应该从中抛出一些异常,还是我可以默默地、很好地结束终止流程?
如果doSomeAction()
不成功,subscribeToResultFromAction()
将不会获得任何结果。
override fun execute(id: String): Flow<Response> {
return repository.subscribeToResultFromAction(id)
.onStart {
repository.doSomeAction(id)
// potentially handle failure here from doSomeAction()
// or handle it differently than in the start of the flow?
}
.map { action ->
when (action.name) {
"NameA" -> Response(action.id, ....)
"NameB" -> Response(action.id, ....)
else -> {
Timber.e("Unexpected action!")
throw java.lang.Exception()
}
}
}
}
最佳答案
您可以使用flow { }
构建器来实现此目的。启动事情的挂起函数可以是流程的一部分。
override fun execute(id: String): Flow<Response> = flow {
try {
repository.doSomeAction(id)
} catch (e: SomeException) {
// Log something?
return@flow // End the flow early
}
repository.subscribeToResultFromAction(id)
.map { action ->
when (action.name) {
"NameA" -> Response(action.id, ....)
"NameB" -> Response(action.id, ....)
else -> {
Timber.e("Unexpected action!")
throw java.lang.Exception()
}
}
}
.let(::emitAll)
}
除了重新抛出异常或静默结束流程之外,另一个选择是使该流程的类型成为一个密封接口(interface),可以包装项目或失败状态。然后收集器可以检查类型并做出相应 react 。
关于android - 在挂起功能可能失败的情况下,结合挂起功能和流功能的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76835171/