使用AlertDialog.create触发java.util.ConcurrentModificationException问题求助
定位与解决java.util.ConcurrentModificationException崩溃(华为设备AlertDialog场景)
崩溃原因分析
从堆栈信息来看,异常是典型的集合迭代过程中被并发修改导致的:
- 触发点是
AlertDialog.create(),华为定制ROM的HwDialogStubImpl初始化时会创建HwSensorManager,后者在获取系统服务的流程中,内部某个ArrayList正在被迭代,同时被其他线程修改,直接触发了ConcurrentModificationException。 - 你的业务代码本身没有直接操作集合,但华为系统服务的实现存在线程不安全的集合操作,创建Dialog的动作恰好触发了这个隐藏的并发冲突。
可行解决方案
1. 延迟Dialog创建避开并发窗口
通过短暂延迟Dialog的创建,避开后台线程与主线程的操作冲突窗口:
@Override public void onClick(View v) { switch (v.getId()) { case R.id.tv_delete: new Handler().postDelayed(() -> { AlertDialog alertDialog = new AlertDialog.Builder(this) .setMessage("确认删除?") .setCancelable(true) .setPositiveButton("确认", (dialog, which) -> doDeleteSelected()) .setNegativeButton("取消", DialogInterface::dismiss) .create(); alertDialog.show(); }, 100); // 100ms延迟,可根据实际情况调整 break; } }
2. 使用自定义Dialog绕过系统实现
直接用自定义布局的Dialog替代系统AlertDialog,避免触发华为定制的系统服务逻辑:
@Override public void onClick(View v) { switch (v.getId()) { case R.id.tv_delete: Dialog customDialog = new Dialog(this, R.style.Theme_AppCompat_Dialog_Alert); customDialog.setContentView(R.layout.custom_confirm_dialog); customDialog.findViewById(R.id.btn_confirm).setOnClickListener(v1 -> { doDeleteSelected(); customDialog.dismiss(); }); customDialog.findViewById(R.id.btn_cancel).setOnClickListener(v1 -> customDialog.dismiss()); customDialog.show(); break; } }
自定义布局custom_confirm_dialog.xml可以完全复刻系统AlertDialog的样式,保证用户体验一致。
3. 针对华为设备使用AppCompatDialog
用AndroidX的AppCompatAlertDialog替代系统Dialog,绕过华为定制的服务逻辑:
@Override public void onClick(View v) { switch (v.getId()) { case R.id.tv_delete: androidx.appcompat.app.AlertDialog.Builder builder = new androidx.appcompat.app.AlertDialog.Builder(this); androidx.appcompat.app.AlertDialog alertDialog = builder .setMessage("确认删除?") .setCancelable(true) .setPositiveButton("确认", (dialog, which) -> doDeleteSelected()) .setNegativeButton("取消", DialogInterface::dismiss) .create(); alertDialog.show(); break; } }
这种方式不需要额外布局,只需确保项目引入了AndroidX依赖。
4. 同步关键操作避免并发修改
如果APP后台有操作与系统服务相关集合的逻辑,通过同步锁确保主线程创建Dialog时,后台线程不会修改对应集合:
private final Object systemServiceLock = new Object(); // 后台线程操作时加锁 private void backgroundSystemOperation() { synchronized (systemServiceLock) { // 执行涉及系统服务集合的操作 } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.tv_delete: synchronized (systemServiceLock) { AlertDialog alertDialog = new AlertDialog.Builder(this) .setMessage("确认删除?") .setCancelable(true) .setPositiveButton("确认", (dialog, which) -> doDeleteSelected()) .setNegativeButton("取消", DialogInterface::dismiss) .create(); alertDialog.show(); } break; } }
验证建议
- 优先选择方案2或3进行灰度发布,监控华为设备的崩溃率变化;
- 针对堆栈中涉及的华为系统版本(如
ActivityThread.java:6753对应的Android版本)进行专项测试,确保修复有效且功能正常。
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

