4

I have code that does blocking operation in while loop (downloads some data from a server). Client does not know how many items are going to be returned in each step. Loop breaks when N items are downloaded.

val n = 10
val list = ArrayList<T>()

while (list.size < n) {
    val lastItemId = list.last()?.id ?: 0
    val items = downloadItems(lastItemId)
    list.addAll(items)
}

downloadItems performs blocking HTTP call and returns list. Now let's assume downloadItems changes and new return type is Observable<Item>. How could I change the code to use RxJava without performing something like blockingGet?

x2bool
  • 2,766
  • 5
  • 26
  • 33

2 Answers2

10

You could use repeatUntil to achieve this:

var totalItems = 0    
var id = 0
Observable.fromCallable {
            downloadItems(id)
        }
        .flatMap {
            list ->
                totalItems += list.size
                id = list.last()?.id ?: 0
                Observable.just(list)
        }
        .repeatUntil({totalItems > n})
        .subscribe({result -> System.out.println(result) })
Anatolii
  • 14,139
  • 4
  • 35
  • 65
1

I think this is elegant way

int n = 10;
Observable.range(0,n)
        .flatMap(i -> downloadItems(i))
        .toList()
        .subscribe(itemsList -> itemsList.forEach(item -> System.out.println(item)));
Tuby
  • 3,158
  • 2
  • 17
  • 36
  • That would call downLoadItems 10 times. I just want to download 10 items. Each call of downloadItems could return more than 0 items, exact number of items is unknown. – x2bool Jul 05 '18 at 15:57
  • I found question that is similar to yours https://stackoverflow.com/questions/50827046/using-flatmap-in-rxjava-2-x – Tuby Jul 06 '18 at 10:03