android - 在挂起功能可能失败的情况下,结合挂起功能和流功能的最佳方法是什么?

标签 android kotlin kotlin-coroutines kotlin-flow

我想将两个不同的函数合并到一个方法中:

接口(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/

相关文章:

android - Kotlin 协程处理错误和实现

android - 协程 - 带有连接的 Dispatchers.Main.immediate 在 runBlocking 内死锁

Android 广播接收器无法工作

kotlin - Spring WebFlux Webclient 作为 Mono 接收应用程序/八位字节流文件

android - 为什么这个 Kotlin Coroutine 会卡住界面?

kotlin - 修饰符 'override' 不适用于 'getter'

android - Kotlin 中 Unresolved 引用

android - Gitignore misc.xml 和 *.iml 与 Android Studio 0.8.9

Android - 如何在完成 Activity 前显示 AlertDialog?

android - 连接 Wifi Direct 组中的多个设备