1

I have API that returns the data by page, something like this:

{
   "count": 100,
   "offset": 0,
   "limit": 25,
   "result": [{}, {}, {}...]
}

I need to get all pages - All data (to execute queries with a different "offset":).

      Observable<MyResponse> call = RetrofitProvider.get().create(MyApi.class).getData(0, 25); // limit and offset
    call.observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.newThread())
            .doOnNext(<saving data>)
            .subscribe(result -> {                   
            }, error -> {             
            });

I'm trying to use RxAndroid and Retrofit. What is the best way this?

Tim
  • 1,606
  • 2
  • 20
  • 32

2 Answers2

2

You can use a publish subject as your source observable, then you keep adding new requests for the next range dynamically.

private Observable<ApiResponse> getData(int start, int end) {
    // Get your API response value
    return RetrofitProvider.get().create(MyApi.class).getData(0, 25);
}

public Observable<ApiResponse> getAllData() {
    final PublishSubject<ApiResponse> subject = PublishSubject.create();
    return subject.doOnSubscribe(new Action0() {
        @Override
        public void call() {
            getData(0, SECTION_SIZE).subscribe(subject);
        }
    }).doOnNext(new Action1<ApiResponse>() {
        @Override
        public void call(ApiResponse apiResponse) {
            if (apiResponse.isFinalResultSet()) {
                subject.onCompleted();
            } else {
                int nextStartValue = apiResponse.getFinalValue() + 1;
                getData(nextStartValue, nextStartValue + SECTION_SIZE).subscribe(subject);
            }
        }
    });
}
cyroxis
  • 3,661
  • 22
  • 37
  • after subject.onCompleted(); subscribe method never called – Tim May 16 '16 at 13:50
  • Yes, good point, the stream will automatically unsubscribe after an onComplete. This can be avoided by only only passing on the onNext & onError calls of the getData observer (as opposed to subscribing). – cyroxis May 19 '16 at 11:53
  • @cyroxis i'm trying to implement your solution in my code but doOnNext is called only twice instead until onCompleted is called.. – NiceToMytyuk Oct 27 '22 at 09:13
  • @cyroxis I'm trying to implement your solution too, but there is no class Action0 and Action1. doOnSubscribe and doOnNext want an Consumer and no Action at all. – Felix Feb 01 '23 at 17:23
  • @Felixthis is from 7 years ago. You are probably on RxJava 2 or 3 which have API changes – cyroxis Feb 13 '23 at 16:09
0

If you know what the count is going to be you can do something like

Observable<MyResponse> call = Observable.empty();
for (int i=0 ; i<count ; i+=25) { 
    call.concatWith(RetrofitProvider.get().create(MyApi.class).getData(i, i+25));
}
JohnWowUs
  • 3,053
  • 1
  • 13
  • 20