您当前的位置: 首页 >  安全

蓝不蓝编程

暂无认证

  • 0浏览

    0关注

    706博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

安卓安全显示dialog-拒绝crash

蓝不蓝编程 发布时间:2019-10-28 15:31:10 ,浏览量:0

背景

安卓显示的dialog是依附于activity的,如果在dialog显示前,activity已经消失了,那dialog显示时就会导致crash. 报错日志如下:

AndroidRuntime: FATAL EXCEPTION: main
    Process: com.cxyzy.safedialog, PID: 32155
    android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@b194e0a for displayid = 0 is not valid; is your activity running?
        at android.view.ViewRootImpl.setView(ViewRootImpl.java:936)
        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:398)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:131)
        at android.app.Dialog.show(Dialog.java:531)
初步解决方案

遇到这样的问题,大家自然也知道怎么办,那就是在显示dialog前对activity进行判断

if (!(activity.isFinishing || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed)) {
    dialog.show()
}

于是代码里到处都充斥着这样的代码. 宝宝表示,很难过.

优化解决方案

归一化处理,让所有dialog集成基础dialog类,在基础dialog类里显示之前做一次判断.

/**
 * 安全显示dialog
 * 对所属activity应销毁的情况进行保护,避免显示时crash
 */
open class SafeBaseDialog : Dialog {
    private var mActivity: Activity

    constructor(activity: Activity) : super(activity) {
        mActivity = activity
    }

    constructor(activity: Activity, themeResId: Int) : super(activity, themeResId) {
        mActivity = activity
    }

    override fun show() {
        if (!isFinishingOrDestroyed(mActivity)) {
            super.show()
        }
    }

    private fun isFinishingOrDestroyed(activity: Activity): Boolean {
        return activity.isFinishing
                || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed)
    }
}
思考题

为什么google官方不直接在Dialog的show方法里做这个判断呢? 是我打开dialog的姿势不太好?

关注
打赏
1639405877
查看更多评论
立即登录/注册

微信扫码登录

0.0926s