Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

onAttach() never called in DialogFragment

I try to implement a callback from a DialogFragment. There is a good example, but they don't open this DialogFragment from a 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 the EditDateDialogFragment at this way (just 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 the public void onAttach(SherlockActivity activity) in the EditDateDialogFragment is never called, because I create the DialogFragment from a Fragment instead of an Activity? How to fix this?

UPDATE: In the RecordDetailFragment I insert this into the onCreate()

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

I changed the instantiation of the DialogFragment to

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

Note the EditDateDialogFragment instead of DialogFragment. I'm not sure how to update the reference in the dialog.

like image 276
No3x Avatar asked Dec 28 '12 13:12

No3x


3 Answers

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) {}

Everything is now fine with DialogFragment.

like image 88
Xavier Lin Avatar answered Nov 13 '22 09:11

Xavier Lin


How to fix this?

I'm guessing that you want the RecordDetailFragment instance to behave as the EditDateDialogListener for the DialogFragment. If yes then you need to explicitly set it(and update it) as the listener:

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

Where setListener() is a method in the EditDialogFragment like this:

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

As the user rotates the phone, for example, the Activity along with its fragments will be recreated and you need to re set the listener to point to the newly created RecordDetailFragment instance(you may want to use a WeakReference for mListener). Something similar you can find in this answer(you'll look for the two fragments in the onCreate).

Edit: In the onCreate method of the 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);
    }
}
like image 9
user Avatar answered Nov 13 '22 09:11

user


Somewhere in the onCreateDialog cast the mListener to the getActivity():

try {
    mListener = (EditDateDialogListener) getActivity();
} catch (Exception e) {
    throw new ClassCastException(getActivity().toString()
            + " must implement EditDateDialogListener");
}
like image 3
Manin Avatar answered Nov 13 '22 09:11

Manin