如何解决ProgressDialog无法关闭及Fragment重复调用问题?
解决ProgressDialog无法关闭及Fragment重复实例化的问题
你的问题核心在于Fragment被重复实例化导致全局ProgressDialog引用混乱,再加上Fragment事务管理的小疏漏,最终导致Dialog无法正常关闭。下面一步步帮你解决:
一、先修复Fragment事务问题(根源:Fragment重复创建)
你代码里混用了android.support.v4.app.FragmentTransaction和原生getFragmentManager(),这会导致Fragment栈管理异常,触发Fragment重复实例化;同时popBackStack的异步特性可能导致新事务提交时栈状态还没更新,也会引发重复创建。
修改你的Fragment替换代码:
new AlertDialog.Builder(getActivity()) .setTitle("Transfer Status") .setMessage(msg) .setCancelable(false) .setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Bundle args = new Bundle(); args.putString("number", mobNumber); args.putString("rno", rnoValue); args.putInt("count",1); // 统一用SupportFragmentManager(对应v4/AndroidX Fragment) FragmentManager fragmentManager = getSupportFragmentManager(); // 用popBackStackImmediate确保回栈操作立即完成,避免栈状态不一致 fragmentManager.popBackStackImmediate(Fragment_New_Money_Transfer.class.getSimpleName(), FragmentManager.POP_BACK_STACK_INCLUSIVE); Fragment_New_Money_Transfer fragment = new Fragment_New_Money_Transfer(); fragment.setArguments(args); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.fragment_container, fragment); // 如果需要加入回栈,确保标签正确(可选) // fragmentTransaction.addToBackStack(Fragment_New_Money_Transfer.class.getSimpleName()); fragmentTransaction.commit(); dialog.dismiss(); } }).show();
二、重构ProgressDialog管理(解决Dialog无法关闭)
全局变量持有ProgressDialog是大坑:当Fragment重建时,新实例会创建新的Dialog,旧Dialog实例被遗弃但仍在显示,导致你调用dismissDialog()时操作的不是当前显示的那个Dialog。
修改方案:
- 把全局
pDialog改成Fragment的实例变量 - 在Fragment生命周期中强制清理Dialog,避免残留
- 优化
showProgress和dismissDialog方法,确保操作当前有效实例
代码修改:
// 把全局pDialog移到Fragment内部作为实例变量 private ProgressDialog pDialog; // 在Fragment销毁视图时强制关闭Dialog,防止内存泄漏和残留 @Override public void onDestroyView() { super.onDestroyView(); dismissDialog(); } public void showProgress() { // 先关闭已有的Dialog,避免重复显示多个加载框 dismissDialog(); pDialog = new ProgressDialog(getActivity()); pDialog.setMessage("Processing..."); pDialog.setCancelable(true); pDialog.show(); } public void dismissDialog() { if (pDialog != null && pDialog.isShowing()) { try { pDialog.dismiss(); } catch (IllegalArgumentException e) { // 捕获Dialog已经被系统销毁的异常,避免崩溃 e.printStackTrace(); } finally { // 置空引用,防止内存泄漏 pDialog = null; } } }
三、网络请求代码小优化
你的网络请求代码基本没问题,但建议加上JSON解析的异常捕获,避免崩溃:
public void getTransferList(){ showProgress(); Ion.with(this) .load(HelperClass.SERVER_ID + HelperClass.postApis+"/mtvaliatemobileno") .setTimeout(HelperClass.timeOut) .setHeader(HelperClass.authName,authToken) .setHeader(HelperClass.contentName,HelperClass.contentValue) .setHeader(HelperClass.secretKeyName,newEncryptedSecretNumber) .setHeader(HelperClass.apiKeyName,encryptedDeviceId) .setJsonObjectBody(json) .asJsonObject() .withResponse() .setCallback(new FutureCallback<Response<JsonObject>>() { @Override public void onCompleted(Exception e, Response<JsonObject> result) { dismissDialog(); // 无论成功失败都要关闭Dialog if (e != null) { e.printStackTrace(); Toast.makeText(getActivity(), "Connection Failed", Toast.LENGTH_SHORT).show(); } else { if (result != null) { try{ Boolean responceMessage = result.getResult().get("res").getAsBoolean(); JsonObject jsonObject1 = result.getResult().get("CardDetail").getAsJsonObject(); // 这里处理你的业务逻辑 } catch (JSONException ex) { ex.printStackTrace(); Toast.makeText(getActivity(), "Data Parse Error", Toast.LENGTH_SHORT).show(); } } } } }); }
额外注意事项
- 如果你已经迁移到AndroidX,建议放弃
ProgressDialog(它已被标记为过时),改用自定义AlertDialog或布局内的ProgressBar,体验更统一。 - 不要给Fragment设置
setRetainInstance(true),除非你明确知道它的作用,否则会导致实例状态混乱。 - 确保所有Fragment相关操作都用同一个
FragmentManager(要么全用原生,要么全用Support/AndroidX),不要混用。
内容的提问来源于stack exchange,提问作者Prabhakaran
相关产品推荐
相关产品推荐

