Search code examples
androidrx-java2

Android RxJava - call multiple single until condition and return a single


I'm stuck on a simple task and i'm pretty sure i'm heading the wrong way. I just need to fetch a list of items. I can only get items by 50 and I don't know the exact number of page.

So what I need to do is make the call and repeat it until I get less than 50 items (which means it's the last page), then return the complete list with an insert in a db

The api call is a single, and I need to return a single. Api call:

@GET("posts")
    fun getItems(@Query("page") page: Int, @Query("per_page") perPage: Int): Single<List<Item>>

This is what I got so far:

fun getItems(): Single<List<Item>> {
    var result = listOf<Item>()
    return Observable.range(1, Integer.MAX_VALUE).concatMapSingle { page ->
            remoteDataSource.getItems(page, 50).map {
                result = it
                it
            }
        }.repeatUntil {
            result.size != 50
        }.single(emptyList()).map {
            localDataSource.insertItems(it)
            it
        }
}

The problem is I got an error when the second page is fetched: java.lang.IllegalArgumentException: Sequence contains more than one element!

How can I do to append each calls to a list and emit that list when I reached the last page? Should I change single to flowable for example?


Solution

  • You need takeUntil to cut off the paging and re-accumulate all the individual pages:

    Observable.range(1, Integer.MAX_VALUE)
    .concatMapSingle { page ->
            remoteDataSource.getItems(page, 50)
    }
    .takeUntil {
            it.size != 50
    }
    .flatMapIterable { it }
    .toList()