如何在onActivityResult中正确显示AlertDialog?解决窗口泄漏问题
嗨,我来帮你搞定这个窗口泄漏的麻烦!你遇到的情况其实挺常见的——当你在onActivityResult回调里弹出AlertDialog时,如果当前的QrScan Activity已经处于销毁(或者快要销毁)的状态,Dialog绑定的窗口就会和Activity脱节,最终导致系统抛出窗口泄漏的异常。
问题根源
onActivityResult的回调时机不一定和Activity的生命周期完全同步,比如用户在扫描过程中按了返回键,Activity已经执行了finish(),但扫描库的回调还在后台处理,这时候你再去创建Dialog,它就会依附在一个已经不存在的Activity窗口上,自然就会泄漏了。
解决方案
这里给你两个靠谱的解决思路,优先推荐第一个:
1. 改用DialogFragment显示弹窗(官方推荐)
DialogFragment是Android官方推荐的弹窗实现方式,它会自动和宿主Activity的生命周期绑定——当Activity销毁时,DialogFragment也会跟着销毁,从根源上避免窗口泄漏。
首先创建一个自定义的DialogFragment子类:
public class SimpleAlertDialogFragment extends DialogFragment { private static final String ARG_TITLE = "title"; private static final String ARG_MESSAGE = "message"; // 静态方法创建实例,传递参数 public static SimpleAlertDialogFragment newInstance(String title, String message) { SimpleAlertDialogFragment fragment = new SimpleAlertDialogFragment(); Bundle args = new Bundle(); args.putString(ARG_TITLE, title); args.putString(ARG_MESSAGE, message); fragment.setArguments(args); return fragment; } @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { // 获取传递的参数 String title = getArguments().getString(ARG_TITLE); String message = getArguments().getString(ARG_MESSAGE); // 构建AlertDialog return new AlertDialog.Builder(requireContext()) .setTitle(title) .setMessage(message) .setPositiveButton("确定", (dialog, which) -> dialog.dismiss()) .create(); } }
然后在onActivityResult中调用它:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); // 替换成你的实际逻辑:判断扫描结果是否符合格式 boolean isResultInvalid = true; if (isResultInvalid) { // 先检查Activity是否还处于活跃状态 if (!isFinishing() && !isDestroyed()) { // 显示DialogFragment SimpleAlertDialogFragment dialogFragment = SimpleAlertDialogFragment.newInstance( "提示", "扫描结果不符合应用格式,请重新扫描"); dialogFragment.show(getSupportFragmentManager(), "simple_alert_tag"); } } }
2. 用普通AlertDialog,但严格检查Activity状态
如果你暂时不想改用DialogFragment,那一定要在创建Dialog前,先确认Activity还没有被销毁:
private void showSimpleAlertDialog(String title, String message) { // 关键判断:检查Activity是否还能正常显示窗口 if (isFinishing() || isDestroyed()) { return; // 如果Activity已经销毁,直接返回,不创建Dialog } AlertDialog alertDialog = new AlertDialog.Builder(this) .setTitle(title) .setMessage(message) .setPositiveButton("确定", null) .create(); alertDialog.show(); }
在onActivityResult里调用这个方法时,同样要先做状态检查,确保Activity处于活跃状态。
总结
优先选择DialogFragment的方案,它能帮你自动处理生命周期的同步问题,不用手动判断各种状态,代码也更健壮。如果用普通AlertDialog,千万别忘了加状态检查,避免窗口泄漏。
内容的提问来源于stack exchange,提问作者zyeek

