Sending events from ViewModel to Activities/Fragments — The right way

In MVVM, Whenever you want to show some toasts or snack bar or sending an intent, you have to send a message from your ViewModel to the activity or fragment and ask it to do the job but the normal methods to do so all have big fallbacks.

In the ShowToast example, ViewModel is deciding when to show the message and what message to show but it is the view that is responsible for showing the actual message. I described View-ViewModel responsibilities in detail in another article. MVVM — How View and ViewModel should communicate?

The wrong ways to handle events

Using an interface, higher-order function or any other sort of callbacks

We can define an interface in the ViewModel and let the Activity/Fragment implement it, then whenever some events happen we simply call the method on the interface. It is simple and straightforward and It works but it is the most stupid choice why? because unlike MVP, in MVVM, we don’t use interfaces for communicating to View and ViewModel should not have any reference to the View. Violating MVVM is not an option!

Sending Events with LiveData

We can put our event data in a LiveData and let the Activity/Fragment observe it. It works but it has some downsides as well. Something like below

But this is not going to work because:

  • Because in case activity/fragment gets destroyed but the ViewModel does not. n configuration change for example view will be notified again about the event and we might end up handling event more than once. If we observe the data after onViewCreated it’s even worth since now every time the view gets destroyed on onDestroryView and gets recreated we will be notified again.
  • In case multiple fragments use the same ViewModel, all of them get notified about the event and handle it simultaneously, and that may not be what we want. We usually want one specific observer to handle the event.

Sending Events with OneTime Only LiveData

There is some implementation of LiveData that will notify the observers only once, this way we don’t get the first issue with the previous solution.

It is a much better solution and I know people using it in production for a while but I still don’t like it because it doesn’t address the second problem with the previous solution and it worth now!, If we have multiple fragments observing the same data, now only one of them gets the data and we don’t know which one!

The right way to handle events!

We can use LiveData and get all the benefits of it, mostly the fact that it is lifecycle aware and It will only notify the view when the view is in an active state but don’t get any previous drawbacks by using a custom wrapper around our data. Our solution would be like this

What’s different now is that We make handling the events explicitly, All the observers get the data and they may get in more than once (since activity/fragment may get destroyed and upon reaction get the data again) but the event will be handled only once but the first observer who decides to handle it.

The last world

In my article, MVVM — How View and ViewModel should communicate? you see that handling some events like showing a toast should be done inside a view but preparing the data for that like witch message to show is ViewModel’s responsibility so we need a way to send this data to View and what I described the right way it’s the best thing I found so far! (It’s not my original solutions though but I don’t remember where I read it first to credit the author).

Also, Let me know what you think in the comment section below, Follow ME if you’re interested to read my other stories as well.

Android Infrastructure Engineer @Spotify Check out my LinkedIn profile http://linkedin.com/in/alzahm/ or email me a.ahmadi.dev@gmail.com

The (retired) Pub(lication) for Android & Tech, focused on Development