RxAndroid - retry observable on click

纵然是瞬间 提交于 2019-12-09 17:53:43

问题


I'm using rxAndroid and rxKotlin in my Android app to handle network requests asynchronously. Now I would like to retry a failed network request only after click on Snackbar button.

My code now:

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

Cities interface for retrofit:

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

Api factory:

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

How can I restart the observable in such way?


回答1:


I can suggest you truly reactive way instead of imperative way.

Insert this code right after subscribe() method:

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

Where update subject is just:

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

And on snackbar click call this method:

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

Everything above the retryWhen method will be literally redone.

Though with this approach error will never go down to the subscriber, you can add error conditioning to the retryHandler flat map, but this is another story.

P.S. sorry, this was Java code with retrolambdas, but you'll easily convert this to Kotlin.



来源:https://stackoverflow.com/questions/36809467/rxandroid-retry-observable-on-click

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!