1

I have a DatePickerDialog that launches successfully in a fragment. When an orientation change occurs the app crashes. The logcat output says the NPE happens with onDismiss in the DatePickerFragment. The onDismiss code is used to toggle the soft keyboard to show again (after the launch of the DatePickerDialog toggles it off). When I remove the onDismiss code the app no longer crashes. What am I missing here?

Here is partial DatePickerFragement file:

public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {

public DatePickerFragment() {
}

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


public void onDismiss(final DialogInterface dialog) {
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(CardViewActivity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
super.onDismiss(dialog);
}

}

This is another fragment I have that handles orientation change with no crashes and keyboard toggles back on correctly:

public class CreateSkycardFragment extends DialogFragment {

public CreateSkycardFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.skyfrag_layout, container, false);
    getDialog().setTitle("Delete card");


    Button btnCancel = (Button) rootView.findViewById(R.id.btnCancel);
    btnCancel.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(CardViewActivity.INPUT_METHOD_SERVICE);
            // The soft keyboard always closes when the DialogFragment is displayed.  So the
            // line below toggles the soft keyboard to show again.
            imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
            // The line below cancels the dialog box.
            getDialog().cancel();
        }
    });

    // When the user clicks "OK" to delete for the "Delete skycard" dialog.
    Button btnOK = (Button) rootView.findViewById(R.id.btnOK);
    btnOK.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // Next line dismisses the DialogFragment
            dismiss();
            // Next line returns to the previous activity (MainActivity) by closing
            // the current activity (CardViewActivity).
            getActivity().finish();
        }
    });

    getDialog().setOnKeyListener(new DialogInterface.OnKeyListener() {
        @Override
        public boolean onKey(android.content.DialogInterface dialog, int keyCode, KeyEvent event) {
            if ((keyCode == android.view.KeyEvent.KEYCODE_BACK)) {
             if (event.getAction()!= KeyEvent.ACTION_DOWN)
                    // Next line dismisses the dialogfragment
                    dismiss();
                    // Next line returns to the previous activity (MainActivity) by closing the fragment and
                    // the current activity (CardViewActivity).
                    getActivity().finish();
                    return true;
                }
            return false;
        }
    });
    return rootView;
}

}

AJW
  • 1,578
  • 3
  • 36
  • 77

1 Answers1

0

See the problem is you started an Activity and you have some variables. When you rotated the screen you destroyed that activity with the variables. Now, when you reach the onDismiss, you're trying to dismiss a value that has already been destroyed on a rotation change.

You could try making your variables static. So it becomes 'staticvariable'.dismissDialog().

Prasanth Louis
  • 4,658
  • 2
  • 34
  • 47
  • Ok, any thoughts on how to fix? – AJW Sep 29 '15 at 00:00
  • you're passing your activity as a parameter to the Input Method Manager, which means it's using it. When your activity is destroyed, using the imm will make the app crash, since it was meant to be used by the other activity. – Pablo Sep 29 '15 at 00:03
  • Making the variables static brings with it its own share of problems. I would advise against it. I think you need to rethink your strategy. – Pablo Sep 29 '15 at 00:05
  • There's not really much of another option in this case. – Prasanth Louis Sep 29 '15 at 00:07
  • I have similar code from another fragment that works fine on orientation change. I am going to edit my question above to show that code. Does that help with why onDismiss is not working in the DatePicker fragment whereas it does work in the other fragment? – AJW Sep 29 '15 at 00:13
  • It's probably because you're doing it on the onCreateView event in the second snippet. – Pablo Sep 29 '15 at 00:19
  • If you really don't want the static variable then try give a tag for your fragment (DialogFragment.show()). Then just access it by FragmentManager.findFragmentByTag. – Prasanth Louis Sep 29 '15 at 00:25
  • Do you mean replace the "getActivity" code for the Input Method Manager line? – AJW Sep 29 '15 at 00:27
  • In your onCreate dialog return your Dialog. Then you can call new MyDialogFragment().show(getSupportFragmentManager(), "tag"); – Prasanth Louis Sep 29 '15 at 00:30
  • Ok so in onCreateDialog use a tag to show (return) the Dialog. But then don't I have to use the tag to call the Input Method Manager in onDismiss rather than getActivity()? – AJW Sep 29 '15 at 00:34
  • Is there any downside to just adding "this.setRetainInstance(true)'" to the onCreateDialog method? – AJW Sep 29 '15 at 02:32
  • There's a good explanation here: http://stackoverflow.com/questions/12640316/further-understanding-setretaininstancetrue – Prasanth Louis Sep 29 '15 at 14:29