Fragment中Progress Dialog重复调用及关闭异常问题求助
看起来你的问题根源主要在两个地方:Fragment事务管理混乱导致多个实例触发API请求,以及Progress Dialog的生命周期未与Fragment正确绑定。下面一步步来解决:
一、先修复Fragment跳转逻辑(避免多个Fragment实例触发请求)
你的返回代码里先add了一个Fragment,紧接着又replace,还把错误的Fragment名称加入回退栈,这会导致Fragment栈混乱,甚至可能出现多个目标Fragment实例同时存在,每个都调用了getData(),自然会触发两次Dialog的显示和关闭。
正确的返回方式应该是直接从回退栈弹出到目标Fragment(Fragment A),或者用更简洁的replace操作,避免多余的add:
// 方案1:如果Fragment A已经在回退栈中,直接弹出到它 getFragmentManager().popBackStack(Fragment_Money_Transfer_Mobile.class.getSimpleName(), FragmentManager.POP_BACK_STACK_INCLUSIVE); // 方案2:如果需要重新创建Fragment A,用干净的replace Fragment_Money_Transfer_Mobile ldf = new Fragment_Money_Transfer_Mobile(); Bundle args = new Bundle(); args.putString("number", mobNumber); ldf.setArguments(args); // 直接替换容器内的Fragment,无需多余操作 FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_container, ldf); transaction.commit();
二、修复Progress Dialog的生命周期管理
你用全局变量管理Dialog,但没有和Fragment的生命周期绑定,容易出现空指针或者重复创建的问题。建议做以下优化:
在Fragment销毁时强制清理Dialog:
在onDestroyView方法中主动关闭Dialog,避免Fragment销毁后Dialog还残留,也防止重建时出现重复实例:@Override public void onDestroyView() { super.onDestroyView(); dismissDialog(); }优化showProgress方法,避免重复创建:
你原来的方法先把pDialog置为null,这会导致即使已有Dialog存在也会被重建。改成先判断状态再创建:public void showProgress() { // 先判断Activity是否可用,避免空指针 if (getActivity() == null || getActivity().isFinishing()) { return; } if (pDialog == null || !pDialog.isShowing()) { pDialog = new ProgressDialog(getActivity()); pDialog.setMessage("Processing..."); pDialog.setCancelable(true); pDialog.show(); } }完善dismissDialog的安全判断:
增加对Activity状态的判断,防止在Activity销毁时调用dismiss引发异常:public void dismissDialog() { if (getActivity() == null || getActivity().isFinishing()) { pDialog = null; return; } if (pDialog != null && pDialog.isShowing()){ pDialog.dismiss(); pDialog = null; } }
三、检查API调用是否被触发多次
确保getData()只在合适的时机调用一次,比如不要在onResume里重复调用,而是只在Fragment首次创建时触发:
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // 仅在Fragment首次创建时调用API,避免重建时重复请求 if (savedInstanceState == null) { getData(); } }
额外建议:改用DialogFragment替代ProgressDialog
ProgressDialog在API 26之后已经被废弃,推荐使用DialogFragment来实现加载弹窗,它能更好地和Fragment生命周期绑定,从根源上避免内存泄漏和显示异常的问题。
示例LoadingDialogFragment:
public class LoadingDialogFragment extends DialogFragment { public static LoadingDialogFragment newInstance() { return new LoadingDialogFragment(); } @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { ProgressDialog dialog = new ProgressDialog(getActivity()); dialog.setMessage("Processing..."); dialog.setCancelable(true); return dialog; } }
在业务Fragment中调用:
private LoadingDialogFragment loadingDialog; public void showProgress() { if (loadingDialog == null || !loadingDialog.isAdded()) { loadingDialog = LoadingDialogFragment.newInstance(); loadingDialog.show(getFragmentManager(), "loading_dialog"); } } public void dismissDialog() { if (loadingDialog != null && loadingDialog.isAdded()) { loadingDialog.dismiss(); loadingDialog = null; } }
内容的提问来源于stack exchange,提问作者Prabhakaran

