2

I am having difficulty understanding how Flowable works in Room. I have Dao methods like this

@Insert(onConflict = OnConflictStrategy.REPLACE)
void upsert(List<Site> sites);

@Query("SELECT * FROM site ORDER BY distance ASC")
Flowable<List<Site>> getSites();

I expect that whenever I call upsert subscriber to Flowable object returned by getSites() will always be called. Is my assumption true?

Here is how I am susbcribing to this flowable

private final Flowable<List<Site>> siteFlowable;
ApiService apiService;
FuelDatabase database;

@Override
public void getSites(boolean showOnlyKeySites) {
    // add sites from cache first, then fetch network -> update cache -> update ui
    disposable = siteFlowable.flatMap(Flowable::fromIterable)
        .filter(site -> site.isValid())
        .buffer(100, TimeUnit.MILLISECONDS, 20)
        .takeUntil(sites -> sites.size() == 0)
        .observeOn(AndroidSchedulers.mainThread())
        .doOnNext(mapView::addPins)
        .subscribe(sites -> {
            Timber.d("Flowable emitted %d items", sites.size());
        }, Timber::e);

    apiService.getSites()
        .map(SiteListResponse::getData)
        .flatMap(Observable::fromIterable)
        .filter(Site::isValidSite)
        .toList().toObservable()
        .subscribe(sites -> {
            Timber.i("Success Fetching %d sites", sites.size());
            database.siteDao().clear();
            database.siteDao().upsert(sites);
        }, throwable -> Timber.e(throwable, "Error fetching sites"));
}

This flowable doesn't get called after upsert() is called. API is returning valid data and data is getting entered into database.

Abhishek Bansal
  • 5,197
  • 4
  • 40
  • 69

1 Answers1

-1

Try this:

apiService.getSites()
    .map(SiteListResponse::getData)
    .flatMap(result -> 
         Observable.fromIterable(result)
        .filter(Site::isValidSite)
        .toList()
        .toFlowable()
    )
    .subscribe(sites -> {
        Timber.i("Success Fetching %d sites", sites.size());
        database.siteDao().clear();
        database.siteDao().upsert(sites);
    }, throwable -> Timber.e(throwable, "Error fetching sites"));
akarnokd
  • 69,132
  • 14
  • 157
  • 192
  • How will this enable `siteFlowable` to emit items? – Abhishek Bansal Dec 26 '17 at 10:38
  • Also `.buffer(100, TimeUnit.MILLISECONDS, 20)` could result in an empty list which you then use to stop the entire flow with `takeUntil()`. – akarnokd Dec 26 '17 at 10:41
  • @akarnod yes that might be causing it to emit only once. Also added definition in question. – Abhishek Bansal Dec 26 '17 at 10:43
  • You may have missing data. I suggest you read [this](https://proandroiddev.com/briefly-about-rxjava-logging-20308b013e6d) and apply `doOnNext`s at various places to figure out where data disappears. – akarnokd Dec 26 '17 at 10:48
  • `buffer` and `takeUntill()` were causing this issue. I had applied them because I did not want my `onNext` to be called too often. Removed them for time-being. – Abhishek Bansal Dec 26 '17 at 11:13