Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJava Android - Load-cache-display data on proper threads

I'm exploring the RxJava and its applicability to Android, and I'm trying to implement a simple load-cache-display use case, as depicted on the following ASCII graph:

                    ---------------
      --- failure --|  Load data  |-- success ---
      |             ---------------             |
      V                                         V
-------------------                       -------------
|  Get from cache |                       |   Filter  |
-------------------                       -------------
      |                                         |
      |                                         V
      |            ----------------       -------------
      ------------>|    Display   |<------|    Cache  |
                   ----------------       -------------

Here's the code that I initially came up with:

subscription = AndroidObservable.bindFragment(this, restClient.getItems())
                .onErrorReturn(new Func1<Throwable, List<Item>>() {
                    @Override public List<Item> call(Throwable throwable) {
                        return itemsDao.getCachedItems();
                    }
                })
                .flatMap(new Func1<ItemContainer, Observable<Item>>() {
                    @Override public Observable<Item> call(ItemContainer itemContainer) {
                        return Observable.from(itemContainer.getItems());
                    }
                })
                .filter(new Func1<Item, Boolean>() {
                    @Override public Boolean call(Item item) {
                        return item.getName().startsWith("B");
                    }
                })
                .toList()
                .map(new Func1<List<Item>, List<Item>>() {
                    @Override public List<Item> call(List<Item> items) {
                        itemsDao.cacheItems(items);
                        return items;
                    }
                })
                .subscribeOn(Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<List<Item>>() {
                    @Override public void call(List<Item> items) {
                        displayData(items);
                    }
                });

As expected, networking and caching are performed on a background thread, and displaying the data happens on UI thread. The problem is that data returned by onErrorReturn() goes through the same filtering and caching cycle, which is redundant. However, if I change the code to this:

subscription = AndroidObservable.bindFragment(this, restClient.getItems())
                    .flatMap(new Func1<ItemContainer, Observable<Item>>() {
                        @Override public Observable<Item> call(ItemContainer itemContainer) {
                            return Observable.from(itemContainer.getItems());
                        }
                    })
                    .filter(new Func1<Item, Boolean>() {
                        @Override public Boolean call(Item item) {
                            return item.getName().startsWith("B");
                        }
                    })
                    .toList()
                    .map(new Func1<List<Item>, List<Item>>() {
                        @Override public List<Item> call(List<Item> items) {
                            itemsDao.cacheItems(items);
                            return items;
                        }
                    })
                    .onErrorReturn(new Func1<Throwable, List<Item>>() {
                        @Override public List<Item> call(Throwable throwable) {
                            return itemsDao.getCachedItems();
                        }
                    })
                    .subscribeOn(Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR))
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Action1<List<Item>>() {
                        @Override public void call(List<Item> items) {
                            displayData(items);
                        }
                    });

displayData() is never called. What would be the right way to compose these observables to implement the scheme that I have?

like image 576
Egor Avatar asked Jun 26 '14 10:06

Egor


People also ask

What is RxJava for Android and how to use it?

RxJava has made life easy for all the Android developers using it. In this blog, we are going to discuss RxJava for Android specifically. What is RxJava? What is RxAndroid? What is RxJava? RxJava is a JVM library for doing asynchronous and executing event-based programs by using observable sequences.

What is caching in Android?

Understanding Caching in Android. When the user launches the program for the first time, there will be no data in memory and no data in the disc cache. As a result, the application will need to make a network call to retrieve the data. It will retrieve data from the network, store it to disc, retain it in-memory cache, and then return the data.

How to multithreading in Android with rxandroid?

RxAndroid introduced the Main Thread required for Android. To work with the multithreading in Android, we will need the Looper and Handler for Main Thread execution. RxAndroid provides AndroidSchedulers.mainThread () which returns a scheduler and that helps in performing the task on the main UI thread that is mainly used in the Android project.

What is androidschedulers mainthread () in Android?

RxAndroid provides AndroidSchedulers.mainThread () which returns a scheduler and that helps in performing the task on the main UI thread that is mainly used in the Android project. So, here AndroidSchedulers.mainThread () is used to provide us access to the main thread of the application to perform actions like updating the UI.


1 Answers

Solved by replacing onErrorReturn() call with onErrorResumeNext(Observable.just(itemsDao.getCachedItems()))

like image 174
Egor Avatar answered Oct 22 '22 13:10

Egor