Crunching RxAndroid — Part 5

In the last episode, we saw that even with the help of Reactive Programming, we risk to leak some important (and heavy) parts of our app, thus wasting users’ resources. They won’t be happy. We won’t be happy as a consequence, so let’s fix this!

RxLifecycle

The guys at Trello faced this issue a while ago and decided to help by releasing in the wild RxLifecycle, an Android library that will automatically manage the unsubscribe routine based on the lifecycle of the target Activity, helping us avoiding leaks. This has the small drawback of having to extend one of the RxActivity, RxAppCompatActivity, RxFragment (with a support version as well) or to provide the Observable ourselves for either ActivityEvent or FragmentEvent.

It doesn’t matter which way you decide to go. Whichever component you pick, the final implementation won’t be much different. What matters is that, thanks to RxLifecycle, our Observable lifespan will be bound to that of the Activity or Fragment it’s used into: this means that our Observable will be unsubscribed in the corresponding “closing” lifecycle event to the one that it was subscribed into. For instance, if you start the Observable in the onResume phase, RxLifecycle will make sure that your Observable will be unsubscribed in the onPause event of the component it was bound to.

The watch begins

Let’s imagine that we want to implement a routine that checks that we do not receive any warning while the Activity it’s declared into is still running, stopping when the hosting component goes reaches the onPause event of the lifecycle. We will then use an interval in order to keep the Observable running while the Activity is up:

Observable.interval(1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::logOnNext,this::logOnError,this::logOnCompleted);

Let’s run this code and see what shows up in logcat:

The onPause method of the Activity is the one announcing that the sun is rising

Something looks fishy here: our Observable keeps on running forever, even if our Activity is being killed!

The watch shall end

To make this code work properly, we need to make the Observable aware of the lifecycle of the component that is hosting it.

One would expect that the library helps us by calling the unsubscribe routine on the Subscription, but this would merely end the emission. RxLifecycle will instead call the onCompleted method on the Observable, and this usually works fine in most of the cases.

The first thing we have to do is importing the libraries into our build.gradle file:

dependencies {
...
compile 'com.trello:rxlifecycle:0.4.0'
compile 'com.trello:rxlifecycle-components:0.4.0'
}

After successfully building the project, we can start using the library. What we need is something emitting the events of our components, so that we can invoke the completion method at the right time. RxLifecycle will allow us to do it in several ways, from emitting the lifecycle events manually to subclass a component that takes care of that for us.

We will take this latter path and extend the RxAppCompatActivity:

public class Part5Activity extends RxAppCompatActivity

At this point, we can use the compose operator in order to bind it to the lifecycle. We could do this automatically or binding it explicitly to an event by invoking the bindUntilActivityEvent static method. By using the first approach, we would simply write:

Observable.interval(1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.compose(bindToLifecycle())
.subscribe(this::logOnNext, this::logOnError,this::logOnCompleted);

Running the sample now will actually fix the issue and prevent our Observable from leaking.

The onCompleted method is called when needed

As usual, you can find the source code for this example on the GitHub repo.

A huge thanks to my friends Sebastiano Poggi, Sebastiano Gottardo and Mark Allison for proof reading this article.