Search code examples
javaandroidandroid-dialogfragment

How to call member function of a class that extend DialogFragment in an Activity


I have written custom DatePickerDialog which extends DialogFragment and implements DatePickerDialog.OnDateSetListener.

public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {

  @Override
  public Dialog onCreateDialog(Bundle savedInstanceState) {
    DatePickerDialog dpd = new DatePickerDialog(getActivity(),
                R.style.MyDialogTheme, this, year, month, day);
    return dpd;
  }

  public void onDateSet(DatePicker view, int year, int month, int day) {

  }

  // own  methods
  String getFormattedDate() {
  }
}

and I call this fragment in my MainActivity.

public class Booking_activity extends AppCompatActivity implements View.OnClickListener {

  public void onClick(View view) {
    if (view == imgView_from) {
      // Initialize a new date picker dialog fragment
      DialogFragment dFragment = new DatePickerFragment();
      // Show the date picker dialog fragment
      dFragment.show(getFragmentManager(), "Date Picker");

      // error 
      dFragment.getFormattedDate();
    } 
  } 
}

Solution

  • The error happens because you try to accessing a not valid method from DialogFragment. You need to create DatePickerFragment with:

    DatePickerFragment dFragment = new DatePickerFragment();
    

    Or casting it:

    DialogFragment dFragment = new DatePickerFragment();
    ((DatePickerDialog)dFragment).getFormattedDate();
    

    But the major flaw is, you try to accessing the getFormattedDate() method before the dFragment object has finish instantiated. Remember that show() is an asynchronous call.

    So you need to inform the Booking_activity activity when the dFragment has finish instantiated. You can use an interface for it. Something like the following:

    1. In your DatePickerFragment, add interface:

      public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
      
        private DatePickerListener mListener;
      
        public interface DatePickerListener {
          void onDialogFinishInitialized();
        }
      
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
          DatePickerDialog dpd = new DatePickerDialog(getActivity(),
                  R.style.MyDialogTheme, this, year, month, day);
      
          // you need to inform the activity when Dialog has finish
          // initialized.
          mListener.onDialogFinishInitialized();
      
          return dpd;
        }
      
        ...
      
        // Need to add the activity as the listener.
        @Override 
        public void onAttach(Activity activity) {
          super.onAttach(activity);
          // This makes sure that the container activity has implemented
          // the listener interface. If not, it throws an exception
          try {
            mListener = (DatePickerListener) activity;
          } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement DatePickerListener");
          }
        }
      
        ...
      
      }
      
    2. Implement the interface in your Activity and call the getFormattedDate() method:

      public class Booking_activity extends AppCompatActivity
      implements View.OnClickListener, DatePickerFragment.DatePickerListener {
        ...
        private DatePickerFragment dFragment;
        ...
        @Override
        public void onDialogFinishInitialized() {
          // You can call the method here now
          dFragment.getFormattedDate();
        }
        ...
      }