Crunching RxAndroid — Part 9
In the last episode of this series, we studied subjects and how they could be helpful while managing the configuration changes of the Activity, together with a retained Fragment. In this article, we are instead exploring another way to retain the running Observable, thanks to the idea and help of my friend and fellow Android Developer Eugenio Marletti.
Hooking in the Activity lifecycle
We are all aware of the onSaveInstanceState/onRestoreInstanceState pair, but what if we do not have a Parcelable or Serializable object such as the Subscription one? Well, a few year ago, before Fragments were a thing, we could have used onRetainNonConfigurationInstance to save the Observable, but that procedure was deprecated in favour of the setRetainInstance method in the Fragment API. Even if it was safe to use (and ironically, exactly what the support Fragments use to restore state), recently Google released a new pair in the FragmentActivity class (upon which the AppCompatActivity inherits) that will allow us to retain a custom state and retrieve it later: let’s welcome the onRetainCustomNonConfigurationInstance/getLastCustomNonConfigurationInstance team!
With the first method, we are able to save the current custom state and we are going to retrieve it later with the second one, making the state itself able to survive the configuration changes, thus being retained properly.
What we did here was to return the current instance of the Observable (line 6), then we just cast it properly when we need it back (line 11). It’s pretty easy, isn’t it?
Creating the right Observable
Now, for the sake of the example, we need a long running Observable, such as this one:
What we need then is to transform the Observable, if necessary, so that it can be observed more than once, surviving the unsubscription and the following resubscription on configuration change. For doing so, we are going to use the replay operator.
The main difference is that this will make our Observable a Connectable one.
Being a Connectable Observable means that it does not start emitting items when it’s subscribed to, but it needs the connect() method to be invoked.
We also specify a buffer size of 1, so that will replay only the last emitted item, thus avoiding wasting memory on older unneeded results.
Since we don’t really need to work with a ConnectableObservable this time, we will use the autoconnect() method, making the connect() call happen automatically the first time we subscribe, and maintaining the connection to the source Observable even if we unsubscribe after.
At this point, we can write a method that will return the proper observable, so that if we already have an instance, it will return it, otherwise it will invoke the method we just described and return us a new one.
Writing the utility methods
Now, we need to wire everything together, so that we can manage the subscription and unsubscription process at a higher level. We will do so by writing down 3 helper methods that will manage the subscription, the unsubscription and the “reset” of the Observable (making the Activity ready for a new iteration).
Wiring up with the lifecycle
Now, we need to make our code work with the Observable, so we need to create it in the onCreate method of the Activity and we subscribe to it right away, while we unsubscribe from it during the onDestroy phase of the Activity (we never know if the Observable completed or not, right?):
Another option would be to make the subscribe and unsubscribe call in the onStart/onStop pair, where you would probably want to do it most of the time. You should instead avoid doing the process during in the onResume/onPause pair, as the Observable would disconnect and reconnect very often, for instance when a popup shows up or during a window focus switch in multiwindow mode.
It is worth mentioning that no fragments were harmed while restoring the Observables.
As usual, you can find the code related to this article on GitHub and remember to share and star if you liked the post.