Show Dialog from ViewModel in Android MVVM Architecture
Asked Answered
O

3

43

About MVVM with new architecture components, I've a question, how should I implement if my app needs to display for example a Dialog with 3 options from some action that happened in my VM? Who is responsible for sending to Activity/Fragment the command to show dialog?

Oenomel answered 23/5, 2017 at 22:30 Comment(0)
M
62

UI-related actions like opening new activities or showing dialogs are triggered from the view (an activity or fragment), not from a ViewModel. The ViewModel doesn't have a reference to the view to prevent leaks and keep the presentation layer "reactive".

You can subscribe your view (activity or fragment) to an observable in the ViewModel so that when it changes, you can start your dialog or new activity from the view. Then the view resets that state in the ViewModel when it's dealt with.

Edit: We wrote official guidance for this: https://developer.android.com/topic/architecture/ui-layer/events

Min answered 25/5, 2017 at 10:31 Comment(7)
What I'm doing is creating a LiveData <Boolean> for every action I need to be triggered in my View to call a new screen or display dialog, but I'm not satisfied with that solution, it does not seem right in my eyes.Oenomel
We're working on a sample for exactly this. I called it LiveEvent and it uses a LiveData<Boolean> to check if it's been called already. Stay tuned.Binetta
I'm interested in LiveEvent sample. Where/when it is going to be published?Towrope
Here it is github.com/googlesamples/android-architecture/blob/…Binetta
How would one go about a confirmation dialog where the viewmodel needs to know the answer to the dialog? the viewmodel triggers the singleevent or the event wrapper, but then, how do you know what the user chose?Wilhite
Hey, JoseAlcérreca can you give some insight into @Wilhite 's question?? Ideally, how should the dialog box result be communicated to the ViewModel? Let's say, its a confirmation box for creating an account & I need to make an API call when the user clicks proceed in the alert dialog. How will I let my VM know t user confirmed?Hubbell
I ended up using the following approach. It solved the 2 way communication issue. Basically you need a callback registered with your notification. blog.tonysneed.com/2011/01/28/…Wilhite
L
0

In Android, most commonly the communication from the ViewModel to the view (Activity/Fragment) is through observing LiveData value. In ViewModel set MutableLiveData value and expose it to the view as LiveData to observe. This is handy when reacting to some state change. Set state persists and is relevant until the next change. It's handy for instance with configuration changes, our view state is preserved in the ViewModel.

But sometimes this is not desirable - with "brief" or "stateless" actions - which only briefly change the state of the UI and are relevant only at the time when action happened - such as action to show a message (be it a toast or a snackbar) - we don't want to re-show an error message 10 min later just because screen rotation occurred; or a navigation action - we don't want to reopen another screen on top. These can be handled with SingleLiveEvent pattern as described in Jose Alcérreca's answer.

I have created a small library for easy implementation for sending such actions - called "brief actions" - actions, not events, because events are something we react to and actions we send/initiate.

You can check it out here:

https://bintray.com/vlad-markovic/maven/com.vladmarkovic.briefactions#read

It's also open source; please feel free to contribute:

https://github.com/vlad-markovic/AndroidBriefActions

Import in Gradle with:

implementation "com.vladmarkovic.briefactions:briefactions:$briefActionsVersion"
Lustick answered 4/8, 2020 at 14:35 Comment(1)
Hi Vlad, your first link is broken!)Dusky
A
0

in dialog:

val viewModel =
        ViewModelProvider(context as ViewModelStoreOwner)[MyViewModel::class.java]
viewModel.sendUserAnswer()
Adductor answered 17/12, 2021 at 11:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.