0

I have created the following extension function :

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))
                }
             }
          }

The extension function then posts the throwable type to a Base Activity and based on the event type posted a relevant dialog is displayed.

If the event is a retry, I would like to retry the failed flow.

For example if the HTTP exception is a 400, and I would like to retry the failed call when retry is selected on the dialog.

Is it possible to add callback to a Kotlin Flow, that has failed and can be called, from a different activity or fragment?

Aniruddh Parihar
  • 3,072
  • 3
  • 21
  • 39
George
  • 2,865
  • 6
  • 35
  • 59

1 Answers1

0

I don't think you want to retry in a separate block, you can organize your code like this


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")
                    }
                }
            }
        }
    }
}

now some explanations

as you already know, flow is cold,if you don't collect it, it will never produce, as a result, if your collect block does not return, the remaining thunk in flow builder after emit will not get executed, you suspend the execution of flow builder by calling suspendCoroutine in collect block, if an HTTP error occurs, you show your dialog, and resume the execution according to user response, if no error happens or users just don't click retry, leave everything alone. the sample code above is somehow misleading, for a general case, you don't supply a retry mechanism when everything goes fine, so the while true block could change to


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
   } 
}

which may comfort you that the flow has an end, but actually it is basically the same

Minami
  • 963
  • 6
  • 21