Tomislav Turcic
Tomislav Turcic

Reputation: 889

Rx + Retrofit + Room - combine Single and Flowable

I have the following problem:

I need to get a Single<> request using Retrofit and combine it with a Flowable<> (Room). Once both complete, I display data on the UI. And I want to get continuous updates from Room.

I've tried using zip operator since that is a common way to do this, but issue with zip is that it waits for data from both sources - meaning each time I get fresh data from the Room, zip doesn't propagate any new emmisions since it also needs fresh data from Retrofit.

My current solution is this one, using combineLatest:

Flowable<UiModel> getData() {
    return Flowable.combineLatest(networkService.getUsers().toFlowable(),
          roomDao.getBooks(), UiModel::success)
            .onErrorReturn(UiModel::error)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .startWith(UiModel.loading());
}

This works, but there's a couple of minor issues. First, there's multiple emissions of UiModel. This is to be expected with combineLatest - I get the first model containing data from database and then the second one when network request completes. I know I could use skip(1) operator to skip the first emission, but I tried replacing my network service with local cache and combineLatest seems to emit only a single UiModel when both data sources finish at the same (similar?) time.

Is there a better way to achieve what I want?

EDIT: I've added .distinctUntilChanged operator before onErrorReturn. That should actually solve any issues, I think.

Upvotes: 1

Views: 1076

Answers (1)

arubin
arubin

Reputation: 146

What if you split the subscription to the Room with Flowable and the network call?

Get cached data from Room when your view is created, if there is data you can display it to the user (with some timestamp to indicate that data was cached)

At the same time make the request to the network (This one can stay on the background thread) and have your network service insert the returned data into the table. If data is different it will update the entry and Flowable will emit, if data is the same table doesn't get updated and Flowable doesn't emit.

The reason for split is to have a better control of observable streams, where one only emits once and the other one emits every time a change occurs.

Upvotes: 1

Related Questions