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.
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.
My error 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)
My using progress dialog class;
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 > 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 < 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();
}
}
I finally found the solution. I was looking for tags with "findFragmentByTag" in my "showDialogAfterDelay" function. But this never came true. I couldn't determine if it was "Added". The piece of code I use to solve this;
fragmentManager.executePendingTransactions();
Just change private void showDialogAfterDelay()
. You have to check if the dialog is already added;
Add : if(dialogFragment != null && dialogFragment.isAdded()) { return; }
That code should run before you are trying to show dialog.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With