RxJava2 : Concat + filter (Cache enabled downloading)
Recently in an Android app, I had a use case to download a list of projects and store in the database. Next time when you go to the same page, app should first check if data is already downloaded or up to date, If not download it from the internet.
I assume you are familiar with some basic RxJava terms like: Observable
, Observer
, Subscriber
and some operators subscribeOn()
, observeOn()
.
Let’s first understand what concat()
,filter()
and first()
do:
concat():
operator concatenate two or more observables in such a way that it acts like single observable. All items of each observable are emitted sequentially as passed in parameter (concat(onservable1, obvervable2,...)
).
filter():
operator accepts a predicate that determine which items to filter out. In case of concat()
here it is being applied to a list returned by each executed observable to check if data exists or is up to date.
first():
operator takes only first emitted item and rejects other emitted values. It takes a default value as a parameter. In case no items emitted by source observable, it emits that default value.
So lets dive into the code:
Here getProjectList()
returns the Observable returned by concat()
operator. Now pay attention to the filter()
and first()
operator, these together determine whether to call next Observable or not, queued using concat()
operator. In filter() operator you can use any predicate that suits your need. Note that an empty array list is passed to first()
operator for a case when both of the observable in concat()
fail to return non-empty list.
We can pass a dummy list with one item saying “Data not available” to the first()
operator to give a nice User experience if there is no items in list:
ArrayList<Project> dummyList = new ArrayList<>();
dummyList.add(new Project("Data not available"));dataRepo.getProjectList(getContext(), adapter.itemsLoaded)
.filter(list -> !list.isEmpty()).first(dummyList)
.subscribe(list -> {
adapter.itemsLoaded += list.size();
adapter.addItems(list);
}, e -> {
// TODO("Handle exception")
});
I hope you will find this article useful. If you know any other better way to do this, please do share in comment section below.
If you like this article please hit clap 👏🏻 icon to support and recommend it to others fellow users.