Using RxJava autoConnect() and Relay to host a stream in a ViewModel

viewmodel-disposing-unpublished

TL;DR

To preserve and share the state of a stream (e.g. for rotations, dialogs), we can host the stream in Android’s ViewModel by using .replay(1).autoConnect() to share the stream’s state and a Relay to share the input.

For example:

Full example here.

Sharing the state

When disposing a connection to an Observable that is a not a ConnectableObservable, the entire stream is disposed.

For example, when subscribing to a network request in an Activity, we lose the state on rotation (or any other configuration change):

viewmodel-disposing-hosting

Examples of stream states

Most RxJava operators have some state that we may want to preserve. Some examples:

.scan() stores its last output:

.combineLatest() stores its last inputs:

.switchMap() maintains the active downstream connection:

Summary

Generally speaking, .autoConnect() (and its fellow operators) allow us to host a stream and maintain its state in a separate lifecycle from its subscribers.

Tying a stream’s lifecycle to a ViewModel’s, we can share its state across rotations. The state and input can also be shared with other views — for example between a dialog and an Activity, or between Fragments in a master-detail design. We can also choose to host streams in other lifecycles, for example for implementing a global in-memory cache, or to have a lifecycle tied to a specific module.

Thanks to Charles Durham.

viewmodel-disposing-published
Cutting tomatoes on a cutting board after grocery delivery.