¿Cómo enviar datos desde DialogFragment a un Fragment?

Tengo un fragmento que abre un Dialogfragment para obtener la entrada del usuario (una cadena y un entero). ¿Cómo envío estas dos cosas al fragmento?

Aquí está mi 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 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 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; } } 

Necesito enviar los datos después de hacer clic en el botón y antes de getDialog().dismiss()

Aquí está el fragmento al que los datos deben enviarse:

 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; } } 

así que una vez que el usuario selecciona una fecha en el Dialogfragment , debe devolver el mes y el año.

Luego, el texto en el botón debe cambiar al mes y año especificado por el usuario.

NOTA: aparte de una o dos llamadas específicas de Fragmento, esta es una receta de enfoque genérica para la implementación del intercambio de datos entre componentes débilmente acoplados. Puede utilizar este enfoque de forma segura para intercambiar datos entre literalmente cualquier cosa, ya sea Fragmentos, Actividades, Diálogos o cualquier otro componente de su aplicación.


Aquí está la receta:

  1. Crear interface (es decir, llamada MyContract ) que contiene una firma del método que se utilizará para pasar los datos, es decir, methodToPassData(... data); .
  2. Asegúrese de que su DialogFragment implemente su contrato: class MyFragment extends Fragment implements MyContract {....}
  3. Al crear DialogFragment establezca su Fragment invocación como fragmento de destino myDialogFragment.setTargetFragment(this, 0); llamando a myDialogFragment.setTargetFragment(this, 0); . Este es el objeto con el que hablarás más tarde.
  4. En su DialogFragment , obtenga ese fragmento de invocación llamando a getTargetFragment(); y lanzar el objeto devuelto a la interfaz de contrato que creó en el paso 1, haciendo: MyContract mHost = (MyContract)getTargetFragment(); . Este paso garantiza que su objective implemente el contrato que necesita (tenga en cuenta que obtendrá ClassCastException si su fragmento de destino no está implementando la interfaz de MyContract ). Esto normalmente no debería suceder, a menos que esté haciendo demasiado copiar y pegar-encoding :). Si su proyecto utiliza un código externo, bibliotecas o complementos, etc., en ese caso debería detectar la excepción y decirle al usuario, es decir, el complemento no es compatible en lugar de bloquearse.
  5. Cuando llegue el momento de devolver los datos, llame a methodToPassData() sobre el objeto que obtuvo anteriormente: ((MyContract)getTargetFragment()).methodToPassData(data); . Si su onAttach() ya arroja y asigna un fragmento de destino a una variable de clase (es decir, mHost ), este código sería simplemente mHost.methodToPassData(data); .
  6. Voilà.

Acaba de pasar satisfactoriamente sus datos del diálogo a invocar fragmento.

Aquí hay otra receta sin usar ninguna interfaz. Solo haciendo uso de setTargetFragment y Bundle para pasar datos entre DialogFragment y Fragment.

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

1. Llame al DialogFragment como se muestra a continuación:

 // 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 el Bundle adicional en una Intent en el DialogFragment para pasar cualquier información al fragmento de destino. El código siguiente en Button#onClick() evento Button#onClick() de DatePickerFragment pasa un String e Integer.

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

3. Use el método CalendarFragment onActivityResult() para leer los valores:

 @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; } }