RxAndroid - повторная попытка, наблюдаемая при нажатии

Я использую rxAndroid и rxKotlin в своем приложении для Android для асинхронной обработки сетевых запросов. Теперь я хотел бы повторить неудачный сетевой запрос только после нажатия кнопки Snackbar.

Мой код сейчас:

val citiesService = ApiFactory.citiesService

citiesService.cities()
    .subscribeOn(Schedulers.newThread()) // fetch List<String>
    .flatMap { Observable.from(it) }     // convert to sequence of String
    .flatMap { city ->
        citiesService.coordinates(city)  // fetch DoubleArray
            .map { City(city, it) }      // convert to City(String, DoubleArray)
        }
    .toList()
    .observeOn(AndroidSchedulers.mainThread())
    .doOnNext {
        listView.setOnItemClickListener { adapterView, view, position, id ->
            onItemClick(it[position])
        }
    }
    .map { it.map { it.getName(activity) } }
    .subscribe(
        { listAdapter = setupAdapter(it) },
        { showErrorSnackbar() }  // handle error
    )

fun showErrorSnackbar() {
        Snackbar.make(listView, getString(R.string.not_available_msg), Snackbar.LENGTH_INDEFINITE)
                .setAction(getString(R.string.snack_retry_btn), {
                    // retry observable
                })
                .show()
    }

Интерфейс городов для дооснащения:

interface CitiesService {

    @GET("api/v1/cities")
    fun cities(): Observable<List<String>>

    @GET("api/v1/cities/{city}/coordinates")
    fun coordinates(@Path("city") city: String): Observable<DoubleArray>
}

Завод Апи:

object ApiFactory {

    val citiesService: CitiesService
        get() = retrofit.create(CitiesService::class.java)

    private val retrofit: Retrofit
        get() = Retrofit
            .Builder()
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl(BASE_URL)
            .build()
}

Как я могу перезапустить наблюдаемое таким образом?


person Michael    schedule 23.04.2016    source источник
comment
Что вызывает запрос? Я не вижу этого из вашего кода. Запускает ли вызов cities() новый запрос?   -  person Byte Welder    schedule 23.04.2016
comment
Я добавил больше кода выше. Да, cities() инициировать новый запрос   -  person Michael    schedule 23.04.2016
comment
Затем вы можете просто обернуть всю реактивную цепочку citiesService.cities()... в новый метод и вызвать его из прослушивателя действий вашего Snackbar.   -  person Byte Welder    schedule 23.04.2016


Ответы (1)


Я могу предложить вам действительно реактивный способ вместо императивного.

Вставьте этот код сразу после метода subscribe():

.retryWhen(retryHandler -> 
           retryHandler.flatMap(nothing -> retrySubject.asObservable()))
.subscribe()

Где тема обновления просто:

@NonNull
private final PublishSubject<Void> retrySubject = PublishSubject.create();

И на закусочной нажмите вызовите этот метод:

public void update() {
    retrySubject.onNext(null);
}

Все, что выше метода retryWhen, будет буквально переделано.

Хотя при таком подходе ошибка никогда не перейдет к подписчику, вы можете добавить обработчик ошибок в плоскую карту retryHandler, но это уже другая история.

P.S. извините, это был код Java с ретролямбдами, но вы легко конвертируете его в Kotlin.

person Roman Iatcyna    schedule 28.03.2017
comment
Я также пробовал этот подход, взятый из android.jlelse.eu/ ОДНАКО Android Studio показывает сообщение Cannot resolve method asObservable() - person Someone Somewhere; 12.01.2018
comment
Получил ту же ошибку, что и метод asObservable(), который был удален из RxJava2, но есть ли другой способ, которым я могу получить то же самое функционирование для повторной попытки при нажатии - person Neha; 19.01.2018