问题叙述
APP业务需求是,使用了一个后台服务监听后台推送通知,有些通知收到后就要弹窗展示给用户,并做相关操作,这样就出现了:
第一个问题
使用Dialog时,当切到后台执行弹窗后,再次将APP切换到前台后,弹窗的UI没有出现,页面上出现一层蒙灰,其下层页面点击事件正常;
第二个问题
使用的DialogFragment弹窗时,因为需求要做成只显示一个弹窗,要关闭已经展示的弹窗,显示新的弹窗,然而APP切到后台后,收到推送执行多次弹窗操作后,再次进入APP发现弹窗失去了焦点,点击时间响应不了;
第一个问题分析-Dialog异常
于是看了下log发现当应用在后台的时候,如果弹窗的DecorView没有写死宽高,在Android10上会出现不测量,不布局的现象;
解决第一个问题
因为是Dialog所以我可以获取到焦点变化监听,回到前台是我判断下是否有焦点,是否已经显示了Dialog,再决定是否发起重绘;
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Window window = getWindow();
if (hasFocus && window != null) {
View decorView = window.getDecorView();
if (decorView.getHeight() == 0 || decorView.getWidth() == 0) {
decorView.requestLayout();
Log.d("aster", "布局异常,重新布局");
}
}
}
第二个问题分析-DialogFragment异常
根据以往经验对第一个问题,首先怀疑是弹窗正常,窗体焦点不明原因丢失导致的,但是真正等debug时,发现代码在后台弹出多个弹窗时,我的业务逻辑是要在弹出下一个弹窗时关闭上一个弹窗,这是DialogFragment出现了报错:
IllegalStateException: Can not perform this action after onSaveInstanceState
解决第二个问题
这个问题就很好解决了
因为 onSaveInstanceState()方法是在该Activity即将被销毁前调用,来保存Activity数据的,如果在保存完状态后再给它添加 Fragment 或者 dismiss (DialogFragment类方法)就会出错。
Fragment的此种报错多见于使用commit()方法时的报错,将该方法使用commitAllowingStateLoss()替换即可。
DialogFragment的此种报错一般是在关闭时使用了dismiss()方法;将该方法使用dismissAllowingStateLoss()替换即可。
检查代码逻辑:
//这个confirmDialog 是一个DialogFragment,始终只显示一个弹窗
if (confirmDialog != null) {
confirmDialog.dismiss();
}
//关闭上一个后再重新显示一个弹窗
showPrescriptionFailDialog(prescription_fail_no);
替换关闭方法dismissAllowingStateLoss即可;
问题解决
跑了一下正常显示,问题解决