title: Android java.lang.IllegalStateException: Fragment already added
body: <p>I'm getting a loading object waiting for a request from the webservice. But sometimes this object causes my application to end. I couldn't detect exactly what the error involved.</p>
  
  <p>In order to prevent this error, I called the object "dismiss" and "cancel" while passing the activity, but this did not work. I then assigned a value of "null" which didn't work either. I didn't work again because I thought I was dealing with Tag.</p>
  
  <p>My error code;</p>
  
  <pre><code>2019-03-27 11:51:20.502 29685-29685/com.xxxx.app E/AndroidRuntime: FATAL EXCEPTION: main
      Process: com.xxxx.app, PID: 29685
      java.lang.IllegalStateException: Fragment already added: DelayedProgressDialog{d8bd442 #1 Delaleyed}
          at androidx.fragment.app.FragmentManagerImpl.addFragment(FragmentManager.java:1916)
          at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:765)
          at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
          at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
          at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
          at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
          at androidx.fragment.app.FragmentManagerImpl$1.run(FragmentManager.java:733)
          at android.os.Handler.handleCallback(Handler.java:873)
          at android.os.Handler.dispatchMessage(Handler.java:99)
          at android.os.Looper.loop(Looper.java:214)
          at android.app.ActivityThread.main(ActivityThread.java:6981)
          at java.lang.reflect.Method.invoke(Native Method)
          at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
  </code></pre>
  
  <p>My using progress dialog class;</p>
  
  <pre><code>    public class DelayedProgressDialog extends DialogFragment {
      private static final int DELAY_MILLISECOND = 450;
      private static final int MINIMUM_SHOW_DURATION_MILLISECOND = 300;
      private static final int PROGRESS_CONTENT_SIZE_DP = 80;
  
      private ProgressBar mProgressBar;
      private boolean startedShowing;
      private long mStartMillisecond;
      private long mStopMillisecond;
  
      private FragmentManager fragmentManager;
      private String tag;
      private Handler showHandler;
  
      // default constructor. Needed so rotation doesn't crash
      public DelayedProgressDialog() {
          super();
      }
  
      @NonNull
      @SuppressLint("InflateParams")
      @Override
      public Dialog onCreateDialog(Bundle savedInstanceState) {
          AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
          LayoutInflater inflater = getActivity().getLayoutInflater();
  
          builder.setView(inflater.inflate(R.layout.dialog_progress, null));
          return builder.create();
      }
  
      @Override
      public void onStart() {
          super.onStart();
          mProgressBar = getDialog().findViewById(R.id.progress);
  
          if (getDialog().getWindow() != null) {
              int px = (int) (PROGRESS_CONTENT_SIZE_DP * getResources().getDisplayMetrics().density);
              getDialog().getWindow().setLayout(px, px);
              getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
          }
      }
  
      @Override
      public void show(FragmentManager fm, String tag) {
          if (isAdded())
              return;
  
          this.fragmentManager = fm;
          this.tag = tag;
          mStartMillisecond = System.currentTimeMillis();
          startedShowing = false;
          mStopMillisecond = Long.MAX_VALUE;
  
          showHandler = new Handler();
          showHandler.postDelayed(new Runnable() {
              @Override
              public void run() {
                  // only show if not already cancelled
                  if (mStopMillisecond &gt; System.currentTimeMillis())
                      showDialogAfterDelay();
              }
          }, DELAY_MILLISECOND);
      }
  
      private void showDialogAfterDelay() {
          startedShowing = true;
  
          DialogFragment dialogFragment = (DialogFragment) fragmentManager.findFragmentByTag(tag);
          if (dialogFragment != null) {
              fragmentManager.beginTransaction().show(dialogFragment).commitAllowingStateLoss();
          } else {
              FragmentTransaction ft = fragmentManager.beginTransaction();
              ft.add(this, tag);
              ft.commitAllowingStateLoss();
          }
      }
  
      public void cancel() {
          if(showHandler == null)
              return;
  
          mStopMillisecond = System.currentTimeMillis();
          showHandler.removeCallbacksAndMessages(null);
  
          if (startedShowing) {
              if (mProgressBar != null) {
                  cancelWhenShowing();
              } else {
                  cancelWhenNotShowing();
              }
          } else
              dismiss();
      }
  
      private void cancelWhenShowing() {
          if (mStopMillisecond &lt; mStartMillisecond + DELAY_MILLISECOND + MINIMUM_SHOW_DURATION_MILLISECOND) {
              final Handler handler = new Handler();
              handler.postDelayed(new Runnable() {
                  @Override
                  public void run() {
                      dismiss();
                  }
              }, MINIMUM_SHOW_DURATION_MILLISECOND);
          } else {
              dismiss();
          }
      }
  
      private void cancelWhenNotShowing() {
          final Handler handler = new Handler();
          handler.postDelayed(new Runnable() {
              @Override
              public void run() {
                  dismiss();
              }
          }, DELAY_MILLISECOND);
      }
  
      @Override
      public void dismiss() {
          FragmentTransaction ft = fragmentManager.beginTransaction();
          ft.remove(this);
          ft.commitAllowingStateLoss();
      }
  }
  </code></pre>