Daher verwende ich flatMap mit RxJava, um einige API-Aufrufe zu verketten, die Singles zurückgeben, und habe mich gefragt, wie ich abhängig von meiner eigenen Bedingung ein benutzerdefiniertes Throwable an die subscribe-Methode in der flatmap-Methode übergeben kann.

Dies ist in einer Android Kotlin-App, die MVVM und RxJava2 / RxAndroid für Datenoperationen verwendet. Ich versuche, eine Reihe von API-Aufrufen zu verketten, die Singles mithilfe der Flatmap-Methode zurückgeben. Jedes Mal, wenn ich eine neue API-Methode nach der vorherigen aufrufen möchte, möchte ich überprüfen, ob die Antwort des vorherigen Aufrufs erfolgreich war. Wenn die Antwort des vorherigen Aufrufs erfolgreich war, rufe ich einfach die nächste API-Methode in der Flatmap auf und alles ist in Ordnung. Wenn die Antwort des vorherigen Aufrufs jedoch nicht erfolgreich war, möchte ich ein benutzerdefiniertes Throwable übergeben, das mir sagt, wo und warum der Vorgang nicht ausgeführt wurde. t erfolgreich. Im Moment einer erfolglosen Antwort übergebe ich eine Single mit einem Nullwert, aber das gibt mir beim Abonnieren nur einen Nullzeiger und das ist nicht sehr hilfreich.

dataManager.apiCall1(dataManager.sessionId!!)
            .subscribeOn(schedulerProvider.io())
            .observeOn(schedulerProvider.ui())
            .flatMap{apiCall1Response ->
                if (apiCall1Response.isSuccessful && apiCall1Response.body() != null) {
                    // First api call was successful, execute api call 2.
                    return@flatMap dataManager.apiCall2(apiCall1Response.importantVal)
                } else {
                    // First api call failed 
                    Single.just(null)
                }
            }.flatMap{apiCall2Response ->
                if (apiCall2Response != null && apiCall2Response.isSuccessful && apiCall2Response.body() != null) {
                    // Second api call was successful, execute api call 3.
                    return@flatMap dataManager.apiCall3(apiCall2Response.importantVal)
                } else {
                    // Second api call failed
                    Single.just(null)
                }
            }.subscribe({apiCall3Response ->
                if (apiCall3Response != null && apiCall3Response.body() != null) {
                   // Success!
                   navigator!!.successful(response)
                } else {
                   // Third api call failed, handle error
                   navigator!!.handleError(Throwable("Api call 3 failed."))
                }
            }, {throwable ->
                // Failure, this is where I want to receive a custom throwable 
                // in case one of the responses were unsuccessful.
                navigator!!.handleError(throwable)
            })

Ich erwarte, dass die Throwable-Nachricht so etwas wie "apiCall1" fehlschlägt, aber die Throwable-Nachricht, wenn ApiCall1 fehlschlägt, ist aufgrund der Single.just (null), die ich übergebe, nur NullPointer.

0
Carson J. 18 Jän. 2019 im 21:51

3 Antworten

Beste Antwort

Verwenden Sie anstelle von Single.just(null) Single.error(). Zum Beispiel: Single.error<TypeHere>(RuntimeException("First api call failed"))

2
Akaki Kapanadze 18 Jän. 2019 im 19:12

Definieren Sie für den am besten lesbaren Code eine Erweiterungsfunktion wie diese

private fun <T> Single<Response<T>>.decorateWithErrorHandling(): Single<T> {
    return this
            .onErrorResumeNext { throwable ->
                // Map network layer exceptions, e.g. IOException to your specific "domain level" exceptions
                Single.error(mapNetworkErrorToSpecificThrowable(throwable))
            }
            .flatMap { response ->
                if (response.isSuccessful) {
                    Single.just(response.body())
                } else {
                    Single.error(convertToSpecificThrowable(response))
                }
            }
}

Verwenden Sie es so:

apiCall1()
    .composeWithErrorHandling().flatMap { result1 -> apiCall2(result1) }
    .composeWithErrorHandling().flatMap { result2 -> apiCall3(result2) }

Etc.

1
Janos Breuer 18 Jän. 2019 im 21:28

Verwenden Sie diesen Code

Wirf eine NullPointerException aus flatMap

Und fange den Fehler mit .onErrorReturn (throwable -> {// deine Arbeit hier})

@Carson J.

0
Roman 18 Jän. 2019 im 19:06