How to send data from DialogFragment to a Fragment?

pass data from dialog to activity android
send data to dialog android
show dialogfragment from fragment
dialogfragment callback to fragment
dialogfragment theme
pass data between fragments
dialog vs dialogfragment
pass values to dialog fragment

I have a fragment that opens a Dialogfragment to get user input (a string, and an integer). How do I send these two things back to the fragment?

Here is my DialogFragment:

public class DatePickerFragment extends DialogFragment {
    String Month;
    int Year;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        getDialog().setTitle(getString(R.string.Date_Picker));
        View v = inflater.inflate(R.layout.date_picker_dialog, container, false);

        Spinner months = (Spinner) v.findViewById(R.id.months_spinner);
        ArrayAdapter<CharSequence> monthadapter = ArrayAdapter.createFromResource(getActivity(),
                R.array.Months, R.layout.picker_row);
              months.setAdapter(monthadapter);
              months.setOnItemSelectedListener(new OnItemSelectedListener(){
                  @Override
                  public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int monthplace, long id) {
                      Month = Integer.toString(monthplace);
                  }
                  public void onNothingSelected(AdapterView<?> parent) {
                    }
              });

        Spinner years = (Spinner) v.findViewById(R.id.years_spinner);
        ArrayAdapter<CharSequence> yearadapter = ArrayAdapter.createFromResource(getActivity(),
             R.array.Years, R.layout.picker_row);
        years.setAdapter(yearadapter);
        years.setOnItemSelectedListener(new OnItemSelectedListener(){
          @Override
          public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int yearplace, long id) {
              if (yearplace == 0){
                  Year = 2012;
              }if (yearplace == 1){
                  Year = 2013;
              }if (yearplace == 2){
                  Year = 2014;
              }
          }
          public void onNothingSelected(AdapterView<?> parent) {}
        });

        Button button = (Button) v.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
           public void onClick(View v) {
               getDialog().dismiss();
            }
        });

        return v;
    }
}

I need to send the data after the button click and before getDialog().dismiss()

Here is the fragment that data needs to be sent to:

public class CalendarFragment extends Fragment {
int Year;
String Month;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    int position = getArguments().getInt("position");
    String[] categories = getResources().getStringArray(R.array.categories);
    getActivity().getActionBar().setTitle(categories[position]);
    View v = inflater.inflate(R.layout.calendar_fragment_layout, container, false);    

    final Calendar c = Calendar.getInstance();
    SimpleDateFormat month_date = new SimpleDateFormat("MMMMMMMMM");
    Month = month_date.format(c.getTime());
    Year = c.get(Calendar.YEAR);

    Button button = (Button) v.findViewById(R.id.button);
    button.setText(Month + " "+ Year);
    button.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
           new DatePickerFragment().show(getFragmentManager(), "MyProgressDialog");
        }
    });
   return v;
  }
}

so once the user selects a date in the Dialogfragment, it must return the month and year.

Then, the text on the button should change to the month and year specified by user.

NOTE: aside from one or two Android Fragment specific calls, this is a generic recipe for implementation of data exchange between loosely coupled components. You can safely use this approach to exchange data between literally anything, be it Fragments, Activities, Dialogs or any other elements of your application.


Here's the recipe:

  1. Create interface (i.e. named MyContract) containing a signature of method for passing the data, i.e. methodToPassMyData(... data);.
  2. Ensure your DialogFragment fullfils that contract (which usually means implementing the interface): class MyFragment extends Fragment implements MyContract {....}
  3. On creation of DialogFragment set your invoking Fragment as its target fragment by calling myDialogFragment.setTargetFragment(this, 0);. This is the object you will be talking to later.
  4. In your DialogFragment, get that invoking fragment by calling getTargetFragment(); and cast returned object to the contract interface you created in step 1, by doing: MyContract mHost = (MyContract)getTargetFragment();. Casting lets us ensure the target object implements the contract needed and we can expect methodToPassData() to be there. If not, then you will get regular ClassCastException. This usually should not happen, unless you are doing too much copy-paste coding :) If your project uses external code, libraries or plugins etc and in such case you should rather catch the exception and tell the user i.e. plugin is not compatible instead of letting the app crash.
  5. When time to send data back comes, call methodToPassMyData() on the object you obtained previously: ((MyContract)getTargetFragment()).methodToPassMyData(data);. If your onAttach() already casts and assigns target fragment to a class variable (i.e. mHost), then this code would be just mHost.methodToPassMyData(data);.
  6. Voilà. You just successfully passed your data from dialog back to invoking fragment.

Send Data from DialogFragment to Fragment, I have sloved the problem thank's to this topic, the seconde response of topic. DatePickerFragment.java @Override public void onDateSet(DatePicker view,  I have a problem with sending data from fragment to fragment. I have DialogFragment named fmonday, it is Viewpager's fragment. I call other DialogFragment, named AlertDFragment to add some data to my fragment. I can read the data from spinner, it's working good. Now I need to send one variable, type string, from AlertDFragment to fmonday.

Here's another recipe without using any Interface. Just making use of the setTargetFragment and Bundle to pass data between DialogFragment and Fragment.

public static final int DATEPICKER_FRAGMENT = 1; // class variable

1. Call the DialogFragment as shown below:

// create dialog fragment
DatePickerFragment dialog = new DatePickerFragment();

// optionally pass arguments to the dialog fragment
Bundle args = new Bundle();
args.putString("pickerStyle", "fancy");
dialog.setArguments(args);

// setup link back to use and display
dialog.setTargetFragment(this, DATEPICKER_FRAGMENT);
dialog.show(getFragmentManager().beginTransaction(), "MyProgressDialog")

2. Use the extra Bundle in an Intent in the DialogFragment to pass whatever info back to the target fragment. The below code in Button#onClick() event of DatePickerFragment passes a String and Integer.

Intent i = new Intent()
        .putExtra("month", getMonthString())
        .putExtra("year", getYearInt());
getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, i);
dismiss();

3. Use CalendarFragment's onActivityResult() method to read the values:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case DATEPICKER_FRAGMENT:
            if (resultCode == Activity.RESULT_OK) {
                Bundle bundle = data.getExtras();
                String mMonth = bundle.getString("month", Month);
                int mYear = bundle.getInt("year");
                Log.i("PICKER", "Got year=" + year + " and month=" + month + ", yay!");
            } else if (resultCode == Activity.RESULT_CANCELED) {
                ...
            }
            break;
    }
}

How to get data from DialogFragment to a Fragment?, The class to send data (the DialogFragment) would use this Fragment we just defined to send the data: private void sendResult(int REQUEST_CODE) { Intent  To receive the data, we use this type of class in the Fragment which initially started the DialogFragment: At this point, you have the string from your EditText from the DialogFragment in the parent fragment. Just use the sendResult(int) method in your TextChangeListener() anonymous class so that the text is sent when you need it.

Here's an approach that illustrates Marcin's answer implemented in kotlin.

1.Create an interface that have a method for passing data in your dialogFragment class.

interface OnCurrencySelected{
    fun selectedCurrency(currency: Currency)
}

2.Add your interface in your dialogFragment constructor.

class CurrencyDialogFragment(val onCurrencySelected :OnCurrencySelected)    :DialogFragment() {}

3.Now make your Fragment implement the interface you just created

class MyFragment : Fragment(), CurrencyDialogFragment.OnCurrencySelected {

override fun selectedCurrency(currency: Currency) {
//this method is called when you pass data back to the fragment
}}

4.Then to show your dialogFragment your just call CurrencyDialogFragment(this).show(fragmentManager,"dialog"). this is the interface object you will be talking to, to pass data back to your Fragment.

5.When you want to sent data back to your Fragment you just call the method to pass data on the interface object your passed in dialogFragment constructor.

onCurrencySelected.selectedCurrency(Currency.USD)
dialog.dismiss()

Passing data to Fragment from Dialog - Anik Dey, Rest of the story is going to show you how we can start a Dialog using DialogFragment and pass data from that dialog fragment to to its hosting  DialogFragment is a specialized Fragment used when you want to display an overlay modal window within an activity that floats on top of the rest of the content. This is typically used for displaying an alert dialog, a confirm dialog, or prompting the user for information within an overlay without having to switch to another Activity.

A good tip is to use the ViewModel and LiveData approach that is the best way to go. Bellow is the code sample about how to share data between Fragments:

class SharedViewModel : ViewModel() {
    val selected = MutableLiveData<Item>()

    fun select(item: Item) {
        selected.value = item
    }
}

class MasterFragment : Fragment() {

    private lateinit var itemSelector: Selector

    private lateinit var model: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        model = activity?.run {
            ViewModelProviders.of(this).get(SharedViewModel::class.java)
        } ?: throw Exception("Invalid Activity")
        itemSelector.setOnClickListener { item ->
            // Update the UI
        }
    }
}

class DetailFragment : Fragment() {

    private lateinit var model: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        model = activity?.run {
            ViewModelProviders.of(this).get(SharedViewModel::class.java)
        } ?: throw Exception("Invalid Activity")
        model.selected.observe(this, Observer<Item> { item ->
            // Update the UI
        })
    }
}

Try it, these new components como to help us, I think that it is more efficient than other approach.

Read more about it: https://developer.android.com/topic/libraries/architecture/viewmodel

How to send data from DialogFragment to a Fragment , How do I send these two things back to the fragment? Here is my DialogFragment: public class DatePickerFragment extends DialogFragment { String Month;  I have a fragment “myFragment” in which I create an object of a “myDialogueFragment”. I want to pass some value to the myDialogueFragment when I invoke it from the myFragment. I have an integer num, that I want to pass to the myDialogueFragment and store that number in a local database along with some other info from the myDialogueFragment.

Dialog Fragment to Fragment, setTargetFragment(this, 0); , passing the calling fragment in the Dialog solved the problem. The class to send data (the DialogFragment) would use this Fragment we just defined to send the data: private void sendResult(int REQUEST_CODE) { Intent intent = new Intent(); intent.putStringExtra(EDIT_TEXT_BUNDLE_KEY, editTextString); getTargetFragment().onActivityResult( getTargetRequestCode(), REQUEST_CODE, intent); }

Sending Data from Dialog to Fragment, DialogFragment is a specialized Fragment used when you want to display an To pass data from a dialog to an Activity, use the same approach you would use  public void onComplete(String time) { // After the dialog fragment completes, it calls this callback. // use the string here } } Now in your DialogFragment , when a user clicks the OK button, send that value back to the Activity via your callback.

Getting results from DialogFragment to calling Fragment using , Passing Data to and From the DialogFragment. In order to pass the data to the  The correct way to instantiate a new fragment and passing values to it, is by creating a bundle, setting arguments on this bundle and then passing it to our fragment.

Comments
  • could you just define the method inside the fragment instead of passing through interfaces?
  • You could, but then the Dialog would have to know the type of fragment that invoked it. This would make the dialog usable only from one specific Fragment. Calling back via an interface is a much more flexible approach.
  • I loved this answer. Not only did it clearly help me out, but you did it without just writing a block of code and explaining the steps. +1
  • Unfortunately, cannot set target fragment for a BottomSheetDialog. Any other ways to accomplish 3rd step for BottomSheetDialog case?
  • Could you convert the following to a sample code cos it is really confusing to read the instructions and implement it
  • Do you have to use onActivityResult? How would you pass data from fragment to dialog - this looks like it is only dialog to fragment?
  • @xphill64x: Yes, onActivityResult is the method in fragment that receives the response from DialogFragment. You can use Bundle to pass data from Fragment to DialogFragment.
  • This is not best approach as you are unable to pass data w/o leaving your target, while using interface does not have this limitiation.
  • @Philip you can pass data as usual with Fragment.setArguments().
  • Great answer sir