I am using DialogFragments for a number of things: choosing item from list, entering text.

What is the best way to return a value (i.e. a string or an item from a list) back to the calling activity/fragment?

Currently I am making the calling activity implement DismissListener and giving the DialogFragment a reference to the activity. The Dialog then calls the OnDimiss method in the activity and the activity grabs the result from the DialogFragment object. Very messy and it doesn't work on configuration change (orientation change) as the DialogFragment loses the reference to the activity.

Thanks for any help.


Solution 1:

Use myDialogFragment.setTargetFragment(this, MY_REQUEST_CODE) from the place where you show the dialog, and then when your dialog is finished, from it you can call getTargetFragment().onActivityResult(getTargetRequestCode(), ...), and implement onActivityResult() in the containing fragment.

It seems like an abuse of onActivityResult(), especially as it doesn't involve activities at all. But I've seen it recommended by official google people, and maybe even in the api demos. I think it's what g/setTargetFragment() were added for.

Solution 2:

As you can see here there is a very simple way to do that.

In your DialogFragment add an interface listener like:

public interface EditNameDialogListener {
    void onFinishEditDialog(String inputText);
}

Then, add a reference to that listener:

private EditNameDialogListener listener;

This will be used to "activate" the listener method(s), and also to check if the parent Activity/Fragment implements this interface (see below).

In the Activity/FragmentActivity/Fragment that "called" the DialogFragment simply implement this interface.

In your DialogFragment all you need to add at the point where you'd like to dismiss the DialogFragment and return the result is this:

listener.onFinishEditDialog(mEditText.getText().toString());
this.dismiss();

Where mEditText.getText().toString() is what will be passed back to the calling Activity.

Note that if you want to return something else simply change the arguments the listener takes.

Finally, you should check whether the interface was actually implemented by the parent activity/fragment:

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    // Verify that the host activity implements the callback interface
    try {
        // Instantiate the EditNameDialogListener so we can send events to the host
        listener = (EditNameDialogListener) context;
    } catch (ClassCastException e) {
        // The activity doesn't implement the interface, throw exception
        throw new ClassCastException(context.toString()
                + " must implement EditNameDialogListener");
    }
}

This technique is very flexible and allow calling back with the result even if your don;t want to dismiss the dialog just yet.