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

Instacart

Instacart

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.
Instacart

Instacart

Author

Instacart is the leading grocery technology company in North America, partnering with more than 2,200 national, regional, and local retail banners to deliver from nearly 100,000 stores across more than 15,000 cities in North America. To read more Instacart posts, you can browse the company blog or search by keyword using the search bar at the top of the page.