OnAttach () was never called in DialogFragment

I am trying to execute a callback from DialogFragment . There is a good example, but they do not open this DialogFragment from Fragment . http://developer.android.com/guide/topics/ui/dialogs.html#PassingEvents

So here is my code:

 public class EditDateDialogFragment extends DialogFragment { // Use this instance of the interface to deliver action events EditDateDialogListener mListener; /* The activity that creates an instance of this dialog fragment must * implement this interface in order to receive event callbacks. * Each method passes the DialogFragment in case the host needs to query it. */ public interface EditDateDialogListener { public void onDialogPositiveClick(DialogFragment dialog); public void onDialogNegativeClick(DialogFragment dialog); } public static EditDateDialogFragment newInstance( int currentCategoryId ) { EditDateDialogFragment p = new EditDateDialogFragment(); Bundle args = new Bundle(); args.putInt("currentRecordId", currentCategoryId); p.setArguments(args); return p; } @Override public void onCreate(Bundle savedInstanceState) { mCurrentRecordId = getArguments().getInt("currentRecordId"); super.onCreate(savedInstanceState); } public void onAttach(SherlockActivity activity) { super.onAttach(activity); try { // Instantiate the EditDateDialogListener so we can send events to the host mListener = (EditDateDialogListener) activity; } catch (ClassCastException e) { // The activity doesn't implement the interface, throw exception throw new ClassCastException(activity.toString() + " must implement EditDateDialogListener"); } } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { LayoutInflater inflater = LayoutInflater.from(getActivity()); final View v = inflater.inflate(R.layout.fragment_dialog_edit_date, null); return new AlertDialog.Builder(getActivity()).setTitle("Set Date...").setView(v).setCancelable(true).setPositiveButton("Confirm", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Log.d("", "Dialog confirmed"); mListener.onDialogPositiveClick(EditDateDialogFragment.this); } }).setNegativeButton("Abort", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Log.d("", "Dialog abort"); dialog.cancel(); } }).create(); } } 

In RecordDetailFragment.java, I implement the interface and create a new instance of EditDateDialogFragment this way (only the important parts):

 public class RecordDetailFragment extends SherlockFragment implements EditDateDialogFragment.EditDateDialogListener { ... DialogFragment editDateFragment = EditDateDialogFragment.newInstance( recordId ); editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFrame"); @Override public void onDialogPositiveClick(DialogFragment dialog) { LOGD(TAG, "Overriden Dialog confirmed"); //((EditDateDialogFragment) dialog).mDatePicker; } @Override public void onDialogNegativeClick(DialogFragment dialog) { // TODO Auto-generated method stub } ... } 

Now public void onAttach(SherlockActivity activity) in EditDateDialogFragment never called because I create a DialogFragment from Fragment instead of Activity ? How to fix it?

UPDATE: In RecordDetailFragment, I insert this in onCreate ()

 if (savedInstanceState != null) { EditDateDialogFragment dpf = (EditDateDialogFragment) getActivity().getSupportFragmentManager().findFragmentByTag("EditDateDialogFragment"); if (dpf != null) { dpf.setListener((EditDateDialogListener) this); } } 

I changed the DialogFragment dialog instance to

  EditDateDialogFragment editDateFragment = EditDateDialogFragment.newInstance( recordId ); editDateFragment.setListener((EditDateDialogListener) this); editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFragment"); 

Pay attention to EditDateDialogFragment instead of DialogFragment. I am not sure how to update the link in the dialog.

+4
source share
4 answers

How to fix it?

I assume that you want the RecordDetailFragment instance to behave like the EditDateDialogListener for DialogFragment . If so, then you need to explicitly set it (and update) as a listener:

 DialogFragment editDateFragment = EditDateDialogFragment.newInstance( recordId ); editDataFragment.setListener(RecordDetailFragment.this); editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFrame"); 

Where setListener() is a method in EditDialogFragment similar to this:

 public void setListener(EditDateDialogListener listener) { mListener = listener; } 

Since the user rotates the phone, for example, Activity along with its fragments will be recreated, and you will need to re-install the listener so that it points to the newly created instance of RecordDetailFragment (you can use WeakReference for mListener ). Something similar you can find in this answer (you will find two snippets in onCreate ).

Edit : in the onCreate method of Activity :

 if (savedInstanceState != null) { RecordDetailFragment df = (RecordDetailFragment) getSupportFragmentManager().findFragmentByTag("rdf"); // "rdf" is the tag used when you add the RecordDetailFragment to the activity EditDateDialogFragment s = (EditDateDialogFragment) getSupportFragmentManager().findFragmentByTag("tag"); // "tag" is the string set as the tag for the dialog when you show it if (s != null) { // the dialog exists so update its listener s.setListener(df); } } 
+8
source

Just jumped into the same problem, the solution was very simple. Instead of overriding

 public void onAttach(Context context) {} 

override this:

 public void onAttach(Activity activity) {} 

Now everything is fine with DialogFragment .

+7
source

Somewhere in onCreateDialog pour mListener into getActivity ():

 try { mListener = (EditDateDialogListener) getActivity(); } catch (Exception e) { throw new ClassCastException(getActivity().toString() + " must implement EditDateDialogListener"); } 
+3
source

Ok, I think it works now. My decision:

  public class EditDateDialogFragment extends DialogFragment { // Use this instance of the interface to deliver action events EditDateDialogListener mListener = new EditDateDialogListener() { @Override public void onDialogPositiveClick(DialogFragment dialog) { //Should always overridden by interface implementing class } @Override public void onDialogNegativeClick(DialogFragment dialog) { //Should always overridden by interface implementing class } }; DatePicker mDatePicker; /* * The activity that creates an instance of this dialog fragment must * implement this interface in order to receive event callbacks. Each method * passes the DialogFragment in case the host needs to query it. */ public interface EditDateDialogListener { public void onDialogPositiveClick(DialogFragment dialog); public void onDialogNegativeClick(DialogFragment dialog); } public void setListener(EditDateDialogListener listener) { mListener = listener; } public static EditDateDialogFragment newInstance(int currentCategoryId) { EditDateDialogFragment p = new EditDateDialogFragment(); Bundle args = new Bundle(); args.putInt("currentRecordId", currentCategoryId); p.setArguments(args); return p; } @Override public void onCreate(Bundle savedInstanceState) { mCurrentRecordId = getArguments().getInt("currentRecordId"); super.onCreate(savedInstanceState); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { LayoutInflater inflater = LayoutInflater.from(getActivity()); final View v = inflater.inflate(R.layout.fragment_dialog_edit_date, null); mDatePicker = (DatePicker) v.findViewById(R.id.dialog_edit_date); return new AlertDialog.Builder(getActivity()).setTitle("Set Date...").setView(v).setCancelable(true).setPositiveButton("Confirm", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Log.d("", "Dialog confirmed"); mListener.onDialogPositiveClick(EditDateDialogFragment.this); } }).setNegativeButton("Abort", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Log.d("", "Dialog abort"); mListener.onDialogNegativeClick(EditDateDialogFragment.this); dialog.cancel(); } }).create(); } } public class RecordDetailFragment extends SherlockFragment implements EditDateDialogFragment.EditDateDialogListener { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { // Update reference // Update reference EditDateDialogFragment attachedDialogFragment = (EditDateDialogFragment) getActivity().getSupportFragmentManager().findFragmentByTag("EditDateDialogFragment"); // "tag" is the string set as the tag for the dialog when you show it if (attachedDialogFragment != null) { // the dialog exists so update its listener attachedDialogFragment.setListener(this); } } } // Called somewhere in the fragment public void showDialog() { EditDateDialogFragment editDateFragment = EditDateDialogFragment.newInstance(recordId); editDateFragment.setListener((EditDateDialogListener) this); editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFragment"); } @Override public void onDialogPositiveClick(DialogFragment dialog) { Log.d("RecordDetailFragment", "Callback Dialog confirmed"); int year = ((EditDateDialogFragment) dialog).mDatePicker.getYear(); Log.d("RecordDetailFragment", "Year of DatePicker: " + year); } @Override public void onDialogNegativeClick(DialogFragment dialog) { Log.d("RecordDetailFragment", "Callback Dialog abort"); // TODO Auto-generated method stub } } 

I'm not sure why DatePicker is still available after closing the dialog box. @Luksprog: What do you think of this? Did you mean it that way?

-3
source

All Articles