How to cancel request in retrofix2.0 (rxandroid) when I request same url

I want to call request when user click button. But when first request not response , user want to change parameter and call new request with same url.

Problem How to cancel first request and call new request with same url.

 ServiceFactory
            .createService()
            .getSomething(page)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeWith(new DefaultObserver<SomthingResponse>() {
                @Override
                public void onNext(@NonNull SomthingResponse response) {
                    showSomthing()
                    hideProgressDialog();

                }

                @Override
                public void onError(@NonNull Throwable e) {
                    hideProgressDialog();
                    showErrorMessage(e.getMessage());
                }

                @Override
                public void onComplete() {

                }
            });

when user click button user will send page parameter to query string but this request have not already finish. User will change to page parameter and send new request. I want to cancel first request.

Thankyou

Upvotes: 0

Views: 507

Answers (2)

skywall
skywall

Reputation: 4005

Answer to your question is switchMap() operator:

public static class User {} // Dummy server response

public Observable<Object> getButtonClicks() {
    return RxView.clicks(findViewById(R.id.button)); // (1)
}

public Single<User> getUserFromApi() {
    return Single.just(new User()) // (2)
            .delay(5, TimeUnit.SECONDS);
}

public void fun() {
    getButtonClicks()
            .subscribeOn(AndroidSchedulers.mainThread())
            .observeOn(Schedulers.io())
            .switchMap(__ -> getUserFromApi().toObservable()) // (3)
            .observeOn(AndroidSchedulers.mainThread()) // (4)
            .subscribeWith(new DisposableObserver<User>() {
                @Override public void onNext(@NonNull User user) {
                    Log.d("fun", "onNext");
                }

                @Override public void onError(@NonNull Throwable e) {
                    Log.d("fun", "onError");
                }

                @Override public void onComplete() {
                    Log.d("fun", "onComplete");
                }
            });
}

What happens here:

  1. Use library RxBinding to get reactive listeners to UI events. This observable emits an Object everytime button is clicked.
  2. Dummy API Observable. Response is delayed to imitate real API.
  3. Switch and map from from click observable to API observable. In case new click object is emitted during execution of the API call, old call is cancelled and new one executed. switchMap() operator marble
  4. You probably want to observe changes in MainThread.

Upvotes: 5

Kaskasi
Kaskasi

Reputation: 1340

You can use a Subject and debounce

http://reactivex.io/documentation/operators/debounce.html

https://github.com/kaskasi/TraktTVSample/blob/master/app/src/main/java/de/fluchtwege/movielist/viewmodel/MovieListViewModel.java

You can check out this sample, it solves a similar problem. When the user enters a query a request is started only when the user stops editing for 1 sec, this way only the result of the last request ist shown:

requestsAPI.queryMovies(query, pagesLoaded)

            .observeOn(schedulerMain)

            .debounce(1000, TimeUnit.MILLISECONDS)

            .subscribe(new Subscriber<List<MovieQuery>>() {

                @Override

                public void onCompleted() {

                }


                @Override

                public void onError(Throwable e) {

                }


                @Override

                public void onNext(List<MovieQuery> movieQueries) {

                    onMoviesLoaded(filterMoviesFromSearchResults(movieQueries));

                }

});

Upvotes: 1

Related Questions