Как отправить пользовательский скинуть через flatmap в RxJava на Android? - PullRequest
0 голосов
/ 18 января 2019

Поэтому я использую flatMap с RxJava для объединения некоторых вызовов API, которые возвращают Singles, и мне было интересно, как передать пользовательский метод throwable методу подписки в метод flatmap, в зависимости от моего состояния.

Это приложение для Android Kotlin, которое использует MVVM и RxJava2 / RxAndroid для операций с данными. Я пытаюсь связать воедино кучу вызовов API, которые возвращают Singles, используя метод flatmap. Каждый раз, когда я хочу вызвать новый метод API после предыдущего, я хочу проверить, был ли ответ предыдущего вызова успешным. Если ответ на предыдущий вызов был успешным, я просто вызываю следующий метод API на плоской карте, и все хорошо, но если ответ на предыдущий вызов не был успешным, я хочу передать пользовательский метод throwing, который сообщает мне, где и почему операция не была выполнена ' т успешно. Прямо сейчас в ситуации неудачного ответа я передаю Single с нулевым значением, но это просто дает мне нулевой указатель при подписке, и это не очень полезно.

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

Я ожидаю, что сбрасываемое сообщение будет выглядеть как «apiCall1», но сбрасываемое сообщение при сбое apiCall1 просто NullPointer из-за Single.just (null), который я передаю.

Ответы [ 3 ]

0 голосов
/ 18 января 2019

Вместо Single.just(null) используйте Single.error().Например: Single.error<TypeHere>(RuntimeException("First api call failed"))

0 голосов
/ 18 января 2019

Для наиболее читабельного кода определите функцию расширения следующим образом:

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

Используйте это так:

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

и т.д.

0 голосов
/ 18 января 2019

Используйте этот код

, создайте исключение NullPointerException из flatMap

и отловите ошибку с помощью .onErrorReturn (throwable -> {// ваша работа здесь})

@ Carson J.

...