【问题标题】:Kotlin Flow, callbackKotlin 流程,回调
【发布时间】:2021-10-28 11:44:45
【问题描述】:

我创建了以下扩展函数:

fun <T> Flow<T>.handleErrors(showError: Boolean = false, retry: Boolean = false, 
                             navigateBack: Boolean = true): Flow<T> =
    catch { throwable ->

        var message: String? = null

        if (showError) {
            when (throwable) {

                is HttpException -> {
                  postEvent(EventType(retry))
                }
             }
          }

然后扩展函数将 throwable 类型发布到 Base Activity,并根据发布的事件类型显示相关对话框。

如果事件是重试,我想重试失败的流程。

例如,如果 HTTP 异常是 400,我想在对话框中选择重试时重试失败的调用。

是否可以将回调添加到失败的 Kotlin 流,并且可以从不同的活动或片段中调用?

【问题讨论】:

    标签: android kotlin-coroutines kotlin-android-extensions kotlin-flow


    【解决方案1】:

    我认为你不想在单独的块中重试,你可以像这样组织你的代码

    
    fun presentDialog(onClick: (Boolean) -> Unit) {
        // some code to compile you dialog / install callbacks / show it
        onClick(true) // user-click-retry
    }
    
    suspend fun main() {
        val source = flow {
            while (true) {
                emit(
                    if (Math.random() > 0.5) Result.success(100) else Result.failure(IllegalArgumentException("woo"))
                )
            }
        }
    
        source.collect { result ->
            suspendCancellableCoroutine<Unit> { cont ->
                result.onSuccess {
                    println("we are done")
                }.onFailure {
                    presentDialog { choice ->
                        if (choice) {
                            cont.resumeWith(Result.success(Unit))
                        } else {
                            println("we are done")
                        }
                    }
                }
            }
        }
    }
    

    现在有一些解释

    你已经知道,flow是cold,如果你不收集它,它永远不会产生,因此,如果你的收集块没有返回,剩余的thunk在flowbuilder之后@987654324 @ 不会被执行, 您通过在collect 块中调用suspendCoroutine 来暂停flow builder 的执行,如果发生HTTP 错误,则显示您的对话框,并根据用户响应恢复执行,如果没有发生错误或用户只是不点击重试,别管一切。上面的示例代码在某种程度上具有误导性,对于一般情况,当一切正常时您不提供重试机制,因此 while true 块可能会更改为

    
    flow {
       do {
         val response = response()
         emit(response)
       } while(response.isFailure)
    }.collect {
       it.onSuccess {  println("of-coz-we-are-done") }.onFailure {
         // suspend execution and show dialog
         // resume execution when user click retry
       } 
    }
    

    这可能会安慰你,流程有尽头,但实际上它基本上是一样的

    【讨论】:

      猜你喜欢
      • 2018-02-07
      • 1970-01-01
      • 2019-09-30
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 2021-01-04
      • 2020-01-10
      • 2019-12-06
      相关资源
      最近更新 更多