Receive result from DialogFragment

2019-01-01 12:03发布

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.

11条回答
萌妹纸的霸气范
2楼-- · 2019-01-01 12:23

In my case I needed to pass arguments to a targetFragment. But I got exception "Fragment already active". So I declared an Interface in my DialogFragment which parentFragment implemented. When parentFragment started a DialogFragment , it set itself as TargetFragment. Then in DialogFragment I called

 ((Interface)getTargetFragment()).onSomething(selectedListPosition);
查看更多
步步皆殇っ
3楼-- · 2019-01-01 12:26

Just to have it as one of the options (since no one mentioned it yet) - you could use an event bus like Otto. So in the dialog you do:

bus.post(new AnswerAvailableEvent(42));

And have your caller (Activity or Fragment) subscribe to it:

@Subscribe public void answerAvailable(AnswerAvailableEvent event) {
   // TODO: React to the event somehow!
}
查看更多
初与友歌
4楼-- · 2019-01-01 12:27

There is a much simpler way to receive a result from a DialogFragment.

First, in your Activity, Fragment, or FragmentActivity you need to add in the following information:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Stuff to do, dependent on requestCode and resultCode
    if(requestCode == 1) { // 1 is an arbitrary number, can be any int
         // This is the return result of your DialogFragment
         if(resultCode == 1) { // 1 is an arbitrary number, can be any int
              // Now do what you need to do after the dialog dismisses.
         }
     }
}

The requestCode is basically your int label for the DialogFragment you called, I'll show how this works in a second. The resultCode is the code that you send back from the DialogFragment telling your current waiting Activity, Fragment, or FragmentActivity what happened.

The next piece of code to go in is the call to the DialogFragment. An example is here:

DialogFragment dialogFrag = new MyDialogFragment();
// This is the requestCode that you are sending.
dialogFrag.setTargetFragment(this, 1);     
// This is the tag, "dialog" being sent.
dialogFrag.show(getFragmentManager(), "dialog");

With these three lines you are declaring your DialogFragment, setting a requestCode (which will call the onActivityResult(...) once the Dialog is dismissed, and you are then showing the dialog. It's that simple.

Now, in your DialogFragment you need to just add one line directly before the dismiss() so that you send a resultCode back to the onActivityResult().

getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, getActivity().getIntent());
dismiss();

That's it. Note, the resultCode is defined as int resultCode which I've set to resultCode = 1; in this case.

That's it, you can now send the result of your DialogFragment back to your calling Activity, Fragment, or FragmentActivity.

Also, it looks like this information was posted previously, but there wasn't a sufficient example given so I thought I'd provide more detail.

EDIT 06.24.2016 I apologize for the misleading code above. But you most certainly cannot receive the result back to the activity seeing as the line:

dialogFrag.setTargetFragment(this, 1);

sets a target Fragment and not Activity. So in order to do this you need to use implement an InterfaceCommunicator.

In your DialogFragment set a global variable

public InterfaceCommunicator interfaceCommunicator;

Create a public function to handle it

public interface InterfaceCommunicator {
    void sendRequestCode(int code);
}

Then when you're ready to send the code back to the Activity when the DialogFragment is done running, you simply add the line before you dismiss(); your DialogFragment:

interfaceCommunicator.sendRequestCode(1); // the parameter is any int code you choose.

In your activity now you have to do two things, the first is to remove that one line of code that is no longer applicable:

dialogFrag.setTargetFragment(this, 1);  

Then implement the interface and you're all done. You can do that by adding the following line to the implements clause at the very top of your class:

public class MyClass Activity implements MyDialogFragment.InterfaceCommunicator

And then @Override the function in the activity,

@Override
public void sendRequestCode(int code) {
    // your code here
}

You use this interface method just like you would the onActivityResult() method. Except the interface method is for DialogFragments and the other is for Fragments.

查看更多
怪性笑人.
5楼-- · 2019-01-01 12:31

Well its too late may be to answer but here is what i did to get results back from the DialogFragment. very similar to @brandon's answer. Here i am calling DialogFragment from a fragment, just place this code where you are calling your dialog.

FragmentManager fragmentManager = getFragmentManager();
            categoryDialog.setTargetFragment(this,1);
            categoryDialog.show(fragmentManager, "dialog");

where categoryDialog is my DialogFragment which i want to call and after this in your implementation of dialogfragment place this code where you are setting your data in intent. The value of resultCode is 1 you can set it or use system Defined.

            Intent intent = new Intent();
            intent.putExtra("listdata", stringData);
            getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
            getDialog().dismiss();

now its time to get back to to the calling fragment and implement this method. check for data validity or result success if you want with resultCode and requestCode in if condition.

 @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);        
        //do what ever you want here, and get the result from intent like below
        String myData = data.getStringExtra("listdata");
Toast.makeText(getActivity(),data.getStringExtra("listdata"),Toast.LENGTH_SHORT).show();
    }
查看更多
闭嘴吧你
6楼-- · 2019-01-01 12:32

Different approach, to allow a Fragment to communicate up to its Activity:

1) Define a public interface in the fragment and create a variable for it

public OnFragmentInteractionListener mCallback;

public interface OnFragmentInteractionListener {
    void onFragmentInteraction(int id);
}

2) Cast the activity to the mCallback variable in the fragment

try {
    mCallback = (OnFragmentInteractionListener) getActivity();
} catch (Exception e) {
    Log.d(TAG, e.getMessage());
}

3) Implement the listener in your activity

public class MainActivity extends AppCompatActivity implements DFragment.OnFragmentInteractionListener  {
     //your code here
}

4) Override the OnFragmentInteraction in the activity

@Override
public void onFragmentInteraction(int id) {
    Log.d(TAG, "received from fragment: " + id);
}

More info on it: https://developer.android.com/training/basics/fragments/communicating.html

查看更多
回忆,回不去的记忆
7楼-- · 2019-01-01 12:39

One easy way I found was the following: Implement this is your dialogFragment,

  CallingActivity callingActivity = (CallingActivity) getActivity();
  callingActivity.onUserSelectValue("insert selected value here");
  dismiss();

And then in the activity that called the Dialog Fragment create the appropriate function as such:

 public void onUserSelectValue(String selectedValue) {

        // TODO add your implementation.
      Toast.makeText(getBaseContext(), ""+ selectedValue, Toast.LENGTH_LONG).show();
    }

The Toast is to show that it works. Worked for me.

查看更多
登录 后发表回答