My colleague and I had an argument. We are translating the application to MVVM Binding. There was a need to start a dialog from a fragment. I do it like this:
In the fragment:
fragmentBinding.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// there's a bunch of code here
alertDialog.show();
}});
A colleague also claims that you need to do this:
In the xml file we write as follows:
android:onClick="@{v -> viewModel.showDialog(context)}"
And in the ViewModel:
fun showDialog(context: Context){
AlertDialog.Builder builder = new AlertDialog.Builder(context);
// there's a bunch of code here
alertDialog.show();
}
Please, tell me, who is right?
CodePudding user response:
ViewModel is responsible for preparing data for the UI, as mentioned in the Android Developer Guides.
Therefore one best practice is never to deal with UI elements in ViewModel. Although the codes will still execute if we pass the Context
to the ViewModel and allow it to show an alertDialog
, you may also need to be aware that the activity/fragment and the ViewModel have different lifecycles, so you need to be careful when passing the Context
to the ViewModel
A more sensible way to handle this, would be for the ViewModel to maintain a flag and prepare the required message using LiveData
or something similar, so that the activity / fragment observes that and actually build and show an AlertDialog
by getting the message from the ViewModel, and notify the ViewModel when the dialog has been shown/clicked, so that the ViewModel will handle the subsequent business logic.
For your particular case, I would leave the AlertDialog
code in the activity/fragment, while if necessary I will retrieve the data from the ViewModel.