Search code examples
javaandroid-alertdialogandroid-viewmodelandroid-mvvm

How to send result of AlertDialog fragment using viewModel?


I have a custom dialog fragment that communicate to its parent using intent. (I've copied it from somewhere). This uses old framework for communicating that some of its methods such as onActivityResult, getTargetFragment() has been deprecated now.

I know that one can replace these deprecated methods with new methods e.g. How to replace setTargetFragment() now that it is deprecated but going such long way just for getting a yes or no result?!

Is there a simple way for doing this? I tried to use ViewModel but doesn't worked!

My ViewModel try: AlertDialogViewModel.java

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class AlertDialogViewModel extends ViewModel {


    private final MutableLiveData<Boolean> mAlertDialogResult = new MutableLiveData();
    public LiveData<Boolean> getAlertDialogResult() {
        return mAlertDialogResult;
    }
    public void setAlertDialogResult(boolean mResult) {
        mAlertDialogResult.setValue(mResult);
    }


}

And inside of MyAlertDialog.java:

public class MyAlertDialog extends DialogFragment {

    AlertDialogViewModel mViewModel;

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        return new MaterialAlertDialogBuilder(requireContext())
                .setTitle(Title)
                .setMessage(MESSAGE)
                .setPositiveButton("YES", (d, b) -> onResult(true))
                .setNegativeButton("NO", (d, b) -> onResult(false))
                .create();
    }

    private void onResult(boolean result) {
       mViewModel.setAlertDialogResult(result);
    }
    private static void showResult(Framgment fragment) {
       dialog.show(fragment.getParentFragmentManager(), null);
    }
}

But this doesn't work when I want toast it as:

MyAlertDialog.showResult(this)
AlertDialogViewModel model = new ViewModelProvider(this).get(AlertDialogViewModel.class);
        model.getAlertDialogResult().observe(this, result-> {
            Toast(this, ""+result,Toast.LENGTH_SHORT).show();
        });

Solution

  • You never initialize your dialog fragment view model. You need to get the same instance as the one being used in the hosting Activity or parent Fragment.

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        // Assumes requireContext() returns the Activity this dialog is shown in
        mViewModel = new ViewModelProvider(requireContext()).get(AlertDialogViewModel.class)
    
        return new MaterialAlertDialogBuilder(requireContext())
                .setTitle(Title)
                .setMessage(MESSAGE)
                .setPositiveButton("YES", (d, b) -> onResult(true))
                .setNegativeButton("NO", (d, b) -> onResult(false))
                .create();
    }
    

    Then make sure you're getting the same instance in your Fragment:

    AlertDialogViewModel model = new ViewModelProvider(requireContenxt()).get(AlertDialogViewModel.class);
    model.getAlertDialogResult().observe(this, result-> {
        Toast(this, ""+result,Toast.LENGTH_SHORT).show();
    });
    

    Lastly, what is dialog and why is this static?

    private static void showResult(Framgment fragment) {
       dialog.show(fragment.getParentFragmentManager(), null);
    }