title: Android: Why DialogFragment return nullpointer on orientation change
body: <p>I have a problem with correct dialog fragment dismissing after that orientation was changed. I guess that's due to old context because after that activity was recreated there was created a new activity and corresponding context. I know that I can set some variable in onSaveInstance to save dialog status and recreate dialog if it`s necessary, or just put one attribute in manifest "orientation". But, maybe, there is something better way to do it to not hardcode it in manifest and not save in onSaveIntance manually? I also tried to use setRetainInstance in both main fragment and dialog fragment but it doesn't help me.</p>
  
  <p><strong>Fragment:</strong></p>
  
  <pre><code>public class MainFragment extends Fragment implements ServiceExecutorListener, OnClickListener, DialogClickListener {
  
  private static final String TAG = MainFragment.class.getName();
  
  private TextView serviceStatus;
  Intent intent;
  Boolean bound = false;
  ServiceConnection sConn;
  RESTService service;
  ProgressDialogFragment pd;
  private Button btnSend, btnCheck;
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      Log.d(TAG, "onCreate");
      setRetainInstance(true);
      intent = new Intent(getActivity(), RESTService.class);
      getActivity().startService(intent);
      sConn = new ServiceConnection() {
  
          @Override
          public void onServiceConnected(ComponentName name, IBinder binder) {
              Log.d(TAG, "MainFragment onServiceConnected");
              service = ((RESTService.MyBinder) binder).getService();
              service.registerListener(MainFragment.this);
              if (service.tasksAreDone())
                  serviceStatus.setText(service.getResult());
              bound = true;
          }
  
          public void onServiceDisconnected(ComponentName name) {
              Log.d(TAG, "MainFragment onServiceDisconnected");
              bound = false;
          }
  
      };
  }
  
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
      View rootView = inflater.inflate(R.layout.main_fragment, container, false);
      serviceStatus = (TextView) rootView.findViewById(R.id.tvServiceStatusValue);
      btnSend = (Button) rootView.findViewById(R.id.btnSend);
      btnCheck = (Button) rootView.findViewById(R.id.btnCheck);
  
      btnSend.setOnClickListener(this);
      btnCheck.setOnClickListener(this);
      return rootView;
  }
  
  @Override
  public void onClick(View v) {
      switch (v.getId()) {
          case R.id.btnSend:
              pd = new ProgressDialogFragment();
              pd.newInstance(null);
              pd.setDialogClickListener(this);
              pd.show(getActivity().getSupportFragmentManager(), "ProgressDialog");
              service.run(RESTService.REQUEST, 7);
              service.run(RESTService.REQUEST, 2);
              service.run(RESTService.REQUEST, 4);
              break;
          case R.id.btnCheck:
              if (service != null)
                  serviceStatus.setText(String.valueOf(service.tasksAreDone()) + service.getTasksCount());
              break;
      }
  }
  
  @Override
  public void onStart() {
      super.onStart();
      Log.d(TAG, "onStart: Bind service");
      getActivity().bindService(intent, sConn, 0);
  }
  
  @Override
  public void onPause() {
      super.onPause();
      Log.d(TAG, "onPause: Unbind service");
      if (!bound)
          return;
      getActivity().unbindService(sConn);
      service.unregisterListener();
      bound = false;
  }
  
  @Override
  public void onComplete(int taskID, int action, String result) {
      Log.d(TAG, "Task #" + taskID + ", action = " + action + " Completed");
      pd.dismiss();
      serviceStatus.setText(result);
  }
  
  @Override
  public void onDialogClick(int action) {
      switch (action) {
          case Dialog.BUTTON_POSITIVE:
              Log.d(TAG, "POSITIVE BUTTON");
              break;
          case Dialog.BUTTON_NEGATIVE:
              Log.d(TAG, "NEGATIVE BUTTON");
              service.removeTasks();
              break;
          case Dialog.BUTTON_NEUTRAL:
              Log.d(TAG, "NEUTRAL BUTTON");
              break;
      }
  }
  
  @Override
  public void onDestroy() {
      super.onDestroy();
      Log.d(TAG, "onDestroy");
  }
  }
  </code></pre>
  
  <p><strong>Dialog:</strong></p>
  
  <pre><code>public class ProgressDialogFragment extends DialogFragment implements OnClickListener {
  
  final String TAG = ProgressDialogFragment.class.getName();
  private DialogClickListener listener;
  
  public ProgressDialogFragment newInstance(Bundle args) {
      ProgressDialogFragment pdf = new ProgressDialogFragment();
      pdf.setArguments(args);
      return pdf;
  }
  
  public void setDialogClickListener(DialogClickListener listener) {
      this.listener = listener;
  }
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setRetainInstance(true);
      Log.d(TAG, "onCreate");
  }
  
  public Dialog onCreateDialog(Bundle savedInstanceState) {
      AlertDialog.Builder adb = new AlertDialog.Builder(getActivity())
              .setTitle("Title!")
              .setPositiveButton(R.string.yes, this)
              .setNegativeButton(R.string.no, this)
              .setNeutralButton(R.string.maybe, this)
              .setCancelable(false)
              .setMessage(R.string.message_text)
              .setOnKeyListener(new OnKeyListener() {
                  @Override
                  public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                      return true;
                  }
              });
      return adb.create();
  }
  
  public void onClick(DialogInterface dialog, int which) {
      if (listener != null)
          listener.onDialogClick(which);
  }
  
  public void onDismiss(DialogInterface dialog) {
      Log.d(TAG, "Dialog: onDismiss, dialog = " + getDialog() + ", retainInstance = " + getRetainInstance());
      // Fix to avoid simple dialog dismiss in orientation change
      if ((getDialog() != null) &amp;&amp; getRetainInstance())  
          getDialog().setDismissMessage(null);
  
  }
  
  public void onCancel(DialogInterface dialog) {
      super.onCancel(dialog);
      Log.d(TAG, "Dialog: onCancel");
  }
  </code></pre>
  
  <p>LOgCat:</p>
  
  <pre><code>04-29 06:17:17.860: E/AndroidRuntime(4202): FATAL EXCEPTION: main
  04-29 06:17:17.860: E/AndroidRuntime(4202): java.lang.NullPointerException
  04-29 06:17:17.860: E/AndroidRuntime(4202):     at android.support.v4.app.DialogFragment.dismissInternal(DialogFragment.java:184)
  04-29 06:17:17.860: E/AndroidRuntime(4202):     at android.support.v4.app.DialogFragment.dismiss(DialogFragment.java:155)
  04-29 06:17:17.860: E/AndroidRuntime(4202):     at com.example.restservice.fragments.MainFragment.onComplete(MainFragment.java:108)
  04-29 06:17:17.860: E/AndroidRuntime(4202):     at com.example.restservice.service.RESTService$1.run(RESTService.java:79)
  04-29 06:17:17.860: E/AndroidRuntime(4202):     at android.os.Handler.handleCallback(Handler.java:605)
  04-29 06:17:17.860: E/AndroidRuntime(4202):     at android.os.Handler.dispatchMessage(Handler.java:92)
  04-29 06:17:17.860: E/AndroidRuntime(4202):     at android.os.Looper.loop(Looper.java:137)
  04-29 06:17:17.860: E/AndroidRuntime(4202):     at android.app.ActivityThread.main(ActivityThread.java:4514)
  04-29 06:17:17.860: E/AndroidRuntime(4202):     at java.lang.reflect.Method.invokeNative(Native Method)
  04-29 06:17:17.860: E/AndroidRuntime(4202):     at java.lang.reflect.Method.invoke(Method.java:511)
  04-29 06:17:17.860: E/AndroidRuntime(4202):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
  04-29 06:17:17.860: E/AndroidRuntime(4202):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
  04-29 06:17:17.860: E/AndroidRuntime(4202):     at dalvik.system.NativeStart.main(Native Method)
  </code></pre>
  
  <p><strong>EDIT:</strong></p>
  
  <p>If I put setRetainInstance(true) in main fragment which calls dialogFragment and in DialogFragment in onCreate method only then I see that getRetainInstance return true and getDialog has object in the process of orientation change(otherwise NPE). In this case I also don`t have NPE BUT there will be following strange behaviour: dialog created and presented, dialog recreated(orientation change) and dismissed(why?), dialog recreated(again orientation changed) and presented(wtf? last time it was dismissed) and so on i.e dialog dismissed on one side but remember that on another side it should be presented. What is that?</p>