Home » Android » rx java – How to create an Observable in Android?

rx java – How to create an Observable in Android?

Posted by: admin June 15, 2020 Leave a comment

Questions:

What I want to do is to create a simple in-memory cache just to try Observables out. However I got stuck because I don’t understand how to create an observable. This is the code I have gotten so far:

public class MovieCache {
    MovieWrapper movieWrapper;

    public Observable<MovieWrapper> getMovies() {
       //How to create and return an Observable<MovieWrapper> here?
    }

    public void setCache(MovieWrapper wrapper) {
        movieWrapper = wrapper;
    }

    public void clearCache() {
        movieWrapper = null;
    }
}

In the getMovies() method I want to create an Observable and return my local field movieWrapper to the subscriber. How can I do this? I tried with using new Observable.just(movieWrapper) but it results in a null exception.

How to&Answers:

Take a look at this tutorial as it does exactly what you are looking for. Basically you use defer() to make sure you always get the latest version of your cached object:

public class MovieCache {
    MovieWrapper movieWrapper;

    public Observable<MovieWrapper> getMovies() {  
        return Observable.defer(new Func0<Observable<MovieWrapper>>() {
            @Override
            public Observable<MovieWrapper> call() {
                return Observable.just(movieWrapper);
            }
        });
    }

    public void setCache(MovieWrapper wrapper) {
        movieWrapper = wrapper;
    }

    public void clearCache() {
        movieWrapper = null;
    }
}

defer() makes sure that you will get the object upon subscription to the Observable not on creation.

Note however that, according to the author of the post:

The only downside to defer() is that it creates a new Observable each
time you get a subscriber. create() can use the same function for each
subscriber, so it’s more efficient. As always, measure performance and
optimize if necessary.

Answer:

As already said, accepted answer has downside

it creates a new Observable each time you get a subscriber

But it is not the only one.

  • Consumer won’t receive any value if he calls getMovies().subscribe(...) before setCache(...) is called.
  • Consumer should resubscribe if he want to receive any updates (let’s say setCache() can be called multiple times.

Of course all of them can be irrelevant in your scenario. I just want to show you another way (I’m sure there are many more).
You can use BehaviorSubject in order to eliminate all these disadvantages.

public class MovieCache {
    private BehaviorSubject<MovieWrapper> mMovieCache = BehaviorSubject.create();

    public void setCache(MovieWrapper wrapper) {
        mMovieCache.onNext(wrapper);
    }

    public Observable<MovieWrapper> getMovieObservable() {
        //use this if consumer want to receive all updates
        return mMovieCache.asObservable();
    }

    public MovieWrapper getMovie() {
        //use this if consumer want to get only current value
        //and not interested in updates
        return mMovieCache.getValue();
    }

    public void clearCache() {
        //CAUTION consumer should be ready to receive null value
        mMovieCache.onNext(null);
        //another way is to call mMovieCache.onCompleted();
        //in this case consumer should be ready to resubcribe
    }

    public static class MovieWrapper {}

}

Take a look at BehaviorSubject marble diagram.