Navigation with MVVM android | CodeUtility


Per the LiveData with SnackBar, Navigation, and other events blog post:

Some data should be consumed only once, like a Snackbar message, a navigation event or a dialog trigger.

Instead of trying to solve this with libraries or extensions to the Architecture Components, it should be faced as a design problem. We recommend you treat your events as part of your state.

They detail the use of a SingleLiveEvent class which ensures that each Navigation event is only received once by an Observer (i.e., your Fragment that has access to your NavController).

The other alternative is to use an ‘Event wrapper’ model where the event must be explicitly marked as handled.

If you were using MVP, P would just call the method on V that triggers navigation.

The equivalent approach in MVVM would be to have a dedicated observable/listener/callback, if done with RxJava it could be driven by a PublishSubject. This satisfies the one-time requirement. If instead you need to respond to events that may be emitted before you subscribed, you can use a BehaviorSubject<Optional<T>> and create it with createDefault(absent<T>()), trigge it with onNext(Optional.of(navigationObject)) and then let the VM know when navigation occurs, and then the VM can clear it with onNext(absent())

Alternatively if you want to work it into some all-encompassing redux/mvi-like state, you might have some state class with all the state including some property that indicates to the view to navigate somewhere, upon receiving/acting on this the View would tell the VM it has done so and the VM would set the state to the same as current but without navigation. e.g. (in Kotlin) state = state.copy(navigateToX = false)