user291701
user291701

Reputation: 39701

Get data back from a fragment dialog - best practices?

I'm converting some of my project to use fragments. How do we communicate with a fragment dialog? I want to create a fragment dialog just to get some text input from the user. When the dialog is dismissed, I'd like to pass the entered text back to the "parent" fragment (the one that started it). Example:

public class MyFragment extends Fragment {

    public void onBtnClick() {
        // What's a good way to get data back from this dialog 
        // once it's dismissed?
        DialogFragment dlgFrag = MyFragmentDialog.newInstance();
        dlgFrag.show(getFragmentManager(), "dialog"); 
    }
}

Thanks

Upvotes: 14

Views: 16551

Answers (4)

juanmeanwhile
juanmeanwhile

Reputation: 2634

There is a new pattern possible which is to share a ViewModel instance between fragments. When instantiating a ViewModelFactory where to get your ViewModels, you have to specify a context as parameter. If the context is the same for both fragments (i.e: the parent activity or parent fragment) and you instantiate the same ViewModel from both fragments, you will get the same instance. This opens a new range of possibilities but also challenges.

Upvotes: 0

Mumasaba
Mumasaba

Reputation: 1

I had this problem once and after I solved it, I created a project that would remind me how I did it. I put the project on github so anyone can see the solution. Here is the link: https://github.com/mumasaba/FragmentFragmentBoss

In this project, we have a simple app with a TextView displaying the words 'Hello World'. This text view is on a fragment which is hosted by the main app activity. This fragment needs to display a new word that the user can enter after they click on the add options menu icon. When clicked, the options menu item calls up a dialog allowing the user to type in their new word. After the user is done, they can click ok to dismiss the dialog and display their new input on the fragment's text view. Therefore, Fragment to DialogFragment communication is illustrated.

Upvotes: 0

juanmeanwhile
juanmeanwhile

Reputation: 2634

As eternalmatt said the given solution does not really answer the question. The way to communicate the dialog with the fragment is calling:

dialog.setTargetFragment(myCallingFragment, requestCode);

The way I do this is by creating the FragmentDialog with an static method where the listener is instanciated an then do the setFragmentTarget() stuff:

public mySuperFragmentDialog extends DialogFragment {
  public interface SuperListener{
     void onSomethingHappened();
  }

  public static mySuperFragmentDialog newInstance(SuperListener listener){
     MySuperFagmentDialog f = new MySuperFragmentDialog();
     f.setTargetFragment((Fragment) listener, /*requestCode*/ 1234);
     return f;
  }
}

To create the dialog from the fragment just do as usual:

Dialog dialog = MySuperFragmentDialog.newInstance(parentFragment);
dialog.show();

Then when you want to comunicate with the fragment which calls the dialog just:

Fragment parentFragment = getTargetFragment();
((SuperListener) parentFragment).onSomethingHappened();

This solution works only when dialog is gonna be created from Fragments and not from Activities, but you can combine both methods ('setFragmentTarget()' and the 'onAttach()' one) plus some Class checks to provide a full solution.

Upvotes: 30

Michele
Michele

Reputation: 6131

A great way to pass this kind of Events is a Callback Interface like descripted in the Android Developers Guide

Your Fragment define a Callback Interface like

public class MyFragment extends Fragment {
    ...
    // Container Activity must implement this interface
    public interface OnArticleSelectedListener {
        public void onArticleSelected(Uri articleUri);
    }
    ...
}

Then you check inside your onAttach Method if the Parent implemented the Callback Interface and save the Instance.

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        mListener = (OnArticleSelectedListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
    }
}

when your Event inside the Fragment happens you simply call the Callback Handler

mListener.onArticleSelected(...);

Hope that helps, further infos here

Upvotes: 14

Related Questions