背景
安卓顯示的dialog是依附于activity的,如果在dialog顯示前,activity已經(jīng)消失了,那dialog顯示時(shí)就會(huì)導(dǎo)致crash.
報(bào)錯(cuò)日志如下:
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)
初步解決方案
遇到這樣的問(wèn)題,大家自然也知道怎么辦,那就是在顯示dialog前對(duì)activity進(jìn)行判斷
if (!(activity.isFinishing || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed)) {
dialog.show()
}
于是代碼里到處都充斥著這樣的代碼.
寶寶表示,很難過(guò).
優(yōu)化解決方案
歸一化處理,讓所有dialog集成基礎(chǔ)dialog類,在基礎(chǔ)dialog類里顯示之前做一次判斷.
/**
* 安全顯示dialog
* 對(duì)所屬activity應(yīng)銷毀的情況進(jìn)行保護(hù)野来,避免顯示時(shí)crash
*/
open class SafeBaseDialog(activity: Activity) : Dialog(activity) {
private var mActivity: Activity = 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方法里做這個(gè)判斷呢?
是我打開(kāi)dialog的姿勢(shì)不太好?