RxJava — функция расширения для подписки

Я пытаюсь использовать RxJava / Retrofit и хочу написать функцию расширения, чтобы обернуть некоторую логику с сетевым результатом.

У меня есть класс NetworkConsumer, который расширяет Consumer.

abstract class NetworkConsumer<T> : Consumer<NetworkResponse<T>> {

    override fun accept(response: NetworkResponse<T>) {
        if (response.isSuccessful()) {
            onSuccess(response.data)
        } else {
            onFailure()
        }
    }

    // other functions such as onSuccess and onFailure
}

Я хочу создать функцию расширения, чтобы позволить мне использовать синтаксис Lambda, как вы можете делать с обычным Consumers.

service.login(email, password)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe({
            result -> 
                // result is the correct object
        }, {
           // handle the error
        }) 

Однако, если я хочу использовать свой NetworkConsumer, я должен сделать:

.subscribe(object : NetworkConsumer<LoginResponse>() {
                    override fun onSuccess(response: LoginResponse) {
                        // ...

Итак, я пытаюсь написать функцию расширения, например:

fun <T> Observable<T>.subscribe(onNext: NetworkConsumer<in T>, onError: Consumer<in Throwable>): Disposable {
    return subscribe(onNext, onError, Functions.EMPTY_ACTION, Functions.emptyConsumer<Any>())
}

Но не компилируется, ошибка:

> Type mismatch. 

> Required: Consumer<in T!>! 

> Found: NetworkConsumer<in T>

person Advice-Dog    schedule 20.03.2018    source источник
comment
Рассматривали ли вы возможность использования RxKotlin (github.com/ReactiveX/RxKotlin), который по сути является просто набором Kotlin? методы расширения для RxJava? Вы также можете просто посмотреть на их код, как реализованы расширения подписчика github.com/ReactiveX/RxKotlin/blob/2.x/src/main/kotlin/io/   -  person Strelok    schedule 20.03.2018
comment
Я изучал это и пробовал несколько вещей, и хотя мне удалось заставить их код работать для функций расширения, я все еще не уверен, как изменить его, чтобы вернуть мне результат, как я хочу. Я не понимаю, как использовать мой NetworkConsumer в этом контексте и разрешить мне направлять все ошибки потребителю onError.   -  person Advice-Dog    schedule 20.03.2018


Ответы (1)


Думаю, это потому, что ваш класс NetworkConsumer расширяется с помощью универсального типа NetworkResponse<T>.

Ваша функция расширения работает с объектом Observable<T>, который ожидает объект Consumer<T> для подписки. Когда вы ставите NetworkConsumer для подписки, это равно Consumer<NetworkResponse<T>> объекту.

Так вот несоответствие: Consumer<T> против Consumer<NetworkResponse<T>>. Вы должны переписать свой класс как NetworkConsumer<T> : Consumer<T>.

Добавлено

Если важно использовать только NetworkResponse типов для потребителя, вы можете сделать следующее:

1) Добавьте расширяющий оператор универсального типа для вашего класса NetworkConsumer.

abstract class NetworkConsumer<T : NetworkResponse<TResponce>, TResponce> : Consumer<T> {...

Здесь T - тип "поместить" внутри родительского класса Consumer, это может быть только NetworkResponse. И TResponce - тип реального ответа, который должен быть помещен в NetworkResponse.

2) Сделайте все ваши методы интерфейса retrofit API возвращающими объект NetworkResponse<...>. После этого ошибок компиляции быть не должно, но этого недостаточно - retrofit не умеет создавать объекты вашего NetworkResponse класса.

3) Я думаю, что этот момент будет самым трудным. Вам нужно создать свою собственную фабрику конвертеров сказать retrofit как создавать для вас объекты ответов. Может помочь этот вопрос, или вы можете найти аналогичные решения в Google.

person Ircover    schedule 20.03.2018
comment
К сожалению, я не могу. Мне нужно обернуть NetworkResponse, потому что все ответы сервера возвращают 200, но сами содержат статус. Поэтому я оборачиваю эту логику, чтобы легко получить фактический статус и полезную нагрузку. - person Advice-Dog; 20.03.2018
comment
@Advice-Dog Я добавил в свой ответ решение с фабрикой преобразователей. Желание это может помочь вам. - person Ircover; 21.03.2018