First of all, I want to apologize for waiting this long for the next blog post. I had a lot of obligations in last three months. Last two parts have almost 60k views! Wow! Thank you all for that!

It is really hard to find one project that covers all the things that are new in Android Development, so I decided to write one.

In this article we will use the following:

0. Android Studio 3 Part 1

1. Kotlin language Part 1

2. Build Variants Part 1

3. ConstraintLayout Part 1

4. Data binding library Part 1

5. MVVM architecture + repository pattern + Android Manager Wrappers Part 2

6. RxJava2 and how it helps us in architecture

7. Dagger 2.11, what is Dependency Injection, why you should use it. Part4

8. Retrofit (with Rx Java2)

9. Room (with Rx Java2)

Now we have new versions for dependencies:

Gradle wrapper 4.1. is now stable

Last Kotlin version is : 1.2.20

Android Architecture Components are now stable 1.0.0 and LifecycleActivity is now deprecated. We should use AppCompatActivity now.

and is now deprecated. We should use now. Now we use targetSdkVersion 27 , buildToolsVersion 27.0.2

All this changes you can find in this commit.

Before writing about RxJava I have great news for you: The Official Android documentation is now showing samples in both, Kotlin and Java! :)

What is RxJava ?

It is not all about RxJava, the concept is much wider. RxJava is just Java implementation of an API for asynchronous programming

with observable streams, reactivex. Actually, it is mix of three concepts: the Observer pattern, the Iterator pattern and functional programming. There are libraries for other programming languages: RxSwift, RxNet, RxJs…

I think it is hard to start with it. Sometimes it is really confusing and if it is not implemented well it can bring you some problems. Still, it is worth to spend the time on it and learn it. I will try to explain RxJava through simple steps.

For the start, let’s answer on simple questions that you will probably ask yourself when you start to read about RxJava:

Is it really needed?

No. RxJava is just one more library that you can use in Android Development. But Kotlin is also not needed, Databinding library is also not needed. I hope you understand what I want to say. It just helps you like all other libraries.

Should I learn RxJava1 before RxJava2?

You can start with RxJava2. Still, it is good for you as an Android developer to know both cause you can be involved in maintaining someone’s else RxJava1 code.

I saw there is RxAndroid, should I use RxAndroid or RxJava?

RxJava can be used in any Java development, not just in Android. For example, RxJava can be used with Spring framework for backend development. RxAndroid is a library that contains what is needed to use RxJava in Android. So, if you want to use RxJava in Android Development, you have to add one more library, RxAndroid. Later, I will explain what RxAndroid adds on the top of RxJava.

We are doing Kotlin, why we don’t use RxKotlin?

There is no need to write one more Rx library cause all Java code is supported in Kotlin world. There is RxKotlin library, but that library is written on top of the RxJava. It just adds Kotlin features to the RxJava. You can use RxJava with Kotlin without using RxKotlin library. For the sake of simplicity, I will not use RxKotlin in this part.

How to add RxJava2 to the project?

To add it, you just need to insert those two lines in build.gradle file:

dependencies {

...

implementation "io.reactivex.rxjava2:rxjava:2.1.8"

implementation "io.reactivex.rxjava2:rxandroid:2.0.1"

...

}

and sync project with gradle files.

What is RxJava contains from?

I would like to separate RxJava into 3 parts:

1. Classes for Observer pattern and data flow: Observables and Observers

2. Schedulers ( concurrency )

3. Operators for data flow

Observables and Observers

We have already explained this pattern. You can think about Observable as the source of the data and Observer the one that gets the data.

There are different ways of creating the observables. The simplest way is to use Observable.just() that takes an item and creates Observable that emits that item.

Let’s go to our GitRepoRemoteDataSource and change our getRepositories method to return Observable:

Observable<ArrayList<Repository>> means that Observable emits array list of Repository objects. If you want to create Observable<Repository> that emits Repository objects you should use Observable.from(arrayList).

.delay(2,TimeUnit.SECONDS) in code makes our Observables to wait 2 seconds before starting to emit the data.

But wait, we didn’t tell when Observable start to emit the data. Observables usually starts to emit the data once when some Observer is subscribed to it.

Note that we don’t need the following interface anymore:

interface OnRepoRemoteReadyCallback {

fun onRemoteDataReady(data: ArrayList<Repository>)

}

Let’s do same thing for GitRepoLocalDataSource:

Note that we don’t need this interface too:

interface OnRepoLocalReadyCallback {

fun onLocalDataReady(data: ArrayList<Repository>)

}

Now we need to change our repository to return Observable :

If there is an internet connection we return Observable from the remote data source, otherwise we return it from the local data source. And, of course, there is no need for OnRepositoryReadyCallback interface too.

As you can guess, we need to change the way how we get data in MainViewModel. Now we should get Observable from gitRepoRepository and subscribe to it. Once when we subscribe Observer to that Observable, Observable will start to emit the data:

Once when an Observer subscribed to the Observable onSubscribe method will be called. Note that we have Disposable as a parameter of onSubscribe method. I will write about it later.

Every time when Observable emits the data onNext() method will be called. Once when Observable finish with emitting onComplete() will be called. After that Observable terminates.

If some error happens onError() will be called and after that Observable terminates. That means Observable will not emit data anymore so onNext() will not be called after that nor onComplete().

Also, take care here. If you try to subscribe to already terminated Observable you will get IllegalStateException.

So, how RxJava helps us?

First, we get rid of all those interfaces. It is kind of boilerplate to make interface for each repository or data source

If we use interfaces and if some error happens in our data layer, our app can crash. Using RxJava error will be returned in onError() method so we can show an appropriate error message to the user.

It is much cleaner cause we always use RxJava for our data layer

I didn’t tell you this before: the previous approach can lead to memory leaks.

How to avoid memory leaks using RxJava2 and ViewModel?

Let’s see lifecycle of the ViewModel again:

Once when Activity is destroyed ViewModel’s onCleared() method will be called. In onCleared() method we should dispose all our Disposables. So let’s do it:

We can improve this code more:

First, instead of Observer, we can use DisposableObserver that implements Disposable and have dispose() method. So we don’t need onSubscribe() method cause we can dispose() directly on DisposableObserver instance.

Second, instead of .subscribe() method that returns void we can use .subscribeWith() method that returns given observer.

We still can improve this code:

We saved Disposable instance so we can dispose it once when onCleared() method is called. But wait, should we do this for each call that we make to data layer? What if we have 10 different calls to data layer? Is it important for us to differ those disposables?

No. There is a smarter way to this. We should keep them all in one bucket and dispose all of them once when onCleared() method is called. We can use CompositeDisposable.

CompositeDisposable, a disposable container that can hold onto multiple other disposables

So, each time when we create Disposable we should hold it into CompositeDisposable:

Thanks to Kotlin extension functions we can improve this more:

Kotlin, similar to C# and Gosu, provides the ability to extend a class with new functionality without having to inherit from the class

Let’s create a new package called extensions and add new RxExtensions.kt file :

Now we can add Disposable object to CompositeDisposable instance using += sign :

Let’s now try to run the application. Once when you tap on Load Data button, the app will crash in two seconds. Then, if you go to logs you will see that error happens inside onNext method and reason of the exception is:

java.lang.IllegalStateException: Cannot invoke setValue on a background thread

Why did that happen?

Schedulers ( concurrency )

RxJava comes with schedulers that give us a possibility to chose on which thread code will be executed.To be more precise, we can choose which thread will observable operate on using subscribeOn() method and which thread observer will operate on using observeOn() method. Usually, all code from data layer should be operated on background thread. For example if we use Schedulers.newThread() ,the scheduler will provide new thread each time when we call it. There are other methods from Schedulers that I will not cover in this blog post for sake of simplicity.

Probably, you already know that all UI code is done on Android Main thread. RxJava is java library and it does not know about Android Main thread. That is the reason why we use RxAndroid. RxAndroid gives us the possibility to choose Android Main thread as the thread where our code will be executed. Obviously, our Observer should operate on Android Main thread.

Let’s do it:

Let’s run app again. Now everything is working :) Good job!

More observables types

We have other observable types:

Single<T> , observable that emits only one item or error

Maybe<T> , observable that emits no items, one item or error

Completable , emits onSuccess event or error.

Flowable<T>, like Observable<T> emits n items, no items or error. While Observable does not support backpressure, Flowable supports it.

What is backpressure?

To remember some concept, I like to make real-life parallel from it:

I think about it as a funnel. If you fill more then your bottleneck can accept it you will overfill it and you will make a mess. Same thing is here. Sometimes your observer cannot process the number of the events that it is receiving so there is a need to slow down.

You can find more about it in RxJava’s documentation.

Operators

The cool thing about RxJava is its operators. Some usual problem that take 10 and more lines are solved in RxJava with just one line of the code. There are operators that help us:

to combine observables

to filter

to do conditions

to convert observables into other types

I will give you one example, let’s finish saving of the data in our GitRepoLocalDataSource. Because we are doing the saving of the data, we will need Completable to simulate it. Let’s say that we also want to simulate delay of 1 second. The really naive way to do it will be:

fun saveRepositories(arrayList: ArrayList<Repository>): Completable {

return Completable.complete().delay(1,TimeUnit.SECONDS)

}

Why this is naive?

Completable.complete() returns a Completable instance that completes immediately when subscribed to.

Once when your Completable completes, it is terminated. So, no operator (delay is one of the operators) will be executed after it. In this case, our Completable will not have any delay. Let’s find the way to do it:

fun saveRepositories(arrayList: ArrayList<Repository>): Completable {

return Single.just(1).delay(1,TimeUnit.SECONDS).toCompletable()

}

Why this way?

Single.just(1) will create Single that emits just number 1. Cause we are using delay(1,TimeUnit.SECONDS) emitting will be delayed by 1 second.

toCompletable() Returns a Completable that discards result of the Single and calls onComplete when this source Single calls onSuccess

So, this code will return Completable that will call onComplete after 1 second.

Now, we should change our GitRepoRepository. Let’s recall the logic. We check for internet connection. If there is an internet connection we have to get data from remote data source, save it in the local data source and return the data. Otherwise, we just get data from local data source. Take a look:

fun getRepositories(): Observable<ArrayList<Repository>> {



netManager.isConnectedToInternet?.let {

if (it) {

return remoteDataSource.getRepositories().flatMap {

return@flatMap localDataSource.saveRepositories(it)

.toSingleDefault(it)

.toObservable()

}

}

}



return localDataSource.getRepositories()

}

Using .flatMap ,once remoteDataSource.getRepositories() emits item, that item will be mapped to new Observable that emits same item. That new Observable we created from Completable that saves the same emitted item in the local data store converting it to Single that emits the same emitted item. Cause we need to return Observable, we have to convert that Single to Observable.

Crazy, huh? Imagine what else we can do with RxJava.

RxJava is a powerful tool!

Play with it. Explore it. I am sure that you will love it.