使用dialog show和cancel常见的异常


上一篇讲了如何使用dialog,这一篇讲一讲使用dialog show()和cancel()常见的异常,也就是一个dialog使用时机的问题。

由于dialog在新建的时候其实都传了一个Contex上下文进去,一般我们都是传使用这个dialog的那个activity的上下文。

1 mPd = new ProgressDialog(this);

也就是其实这一个dialog是和传入的activity绑定着的,所以如果activity已经finish了或者Destroy了,我们再调用dialog的show()或者cancel():

1、finish之后你的dialog其实已经不合activity绑定了,所以会报not attached to window manager

2、由于activity已经不再使用,而你的dialog还引用着这个activity使用,所以会报Activity xxxxxActivity has leaked

出这个问题经常的场景就是比如,后台的asynctask在activity已经退出了还在继续下载,或者自己的操作,操作完了回来还想更新一下dialog通知用户,但是此时dialog对应的activity已经不存在了。。。。

使用dialog和上下文状态或者说时机相关的异常:

dismis或者cancel的时候报了not attached to window manager

12-01 13:54:09.375: E/AndroidRuntime(18146): java.lang.IllegalArgumentException: View=com.android.internal.policy.PhoneWindow$DecorView{b414dcc V.E...... R.....ID 0,0-1026,450} not attached to window manager

12-01 13:54:09.375: E/AndroidRuntime(18146): at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:424)
12-01 13:54:09.375: E/AndroidRuntime(18146): at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:350)
12-01 13:54:09.375: E/AndroidRuntime(18146): at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:116)
12-01 13:54:09.375: E/AndroidRuntime(18146): at android.app.Dialog.dismissDialog(Dialog.java:362)
12-01 13:54:09.375: E/AndroidRuntime(18146): at android.app.Dialog.dismiss(Dialog.java:345)
12-01 13:54:09.375: E/AndroidRuntime(18146): at android.app.Dialog.cancel(Dialog.java:1199)
12-01 13:54:09.375: E/AndroidRuntime(18146): at com.decent.decentdialog.MainActivity$ShowTaskAfterFinish.onProgressUpdate(MainActivity.java:85)
12-01 13:54:09.375: E/AndroidRuntime(18146): at com.decent.decentdialog.MainActivity$ShowTaskAfterFinish.onProgressUpdate(MainActivity.java:1)
12-01 13:54:09.375: E/AndroidRuntime(18146): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:671)
12-01 13:54:09.375: E/AndroidRuntime(18146): at android.os.Handler.dispatchMessage(Handler.java:102)
12-01 13:54:09.375: E/AndroidRuntime(18146): at android.os.Looper.loop(Looper.java:148)
12-01 13:54:09.375: E/AndroidRuntime(18146): at android.app.ActivityThread.main(ActivityThread.java:5417)
12-01 13:54:09.375: E/AndroidRuntime(18146): at java.lang.reflect.Method.invoke(Native Method)
12-01 13:54:09.375: E/AndroidRuntime(18146): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
12-01 13:54:09.375: E/AndroidRuntime(18146): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

最后报了Activity xxxx has leaked,that was originally added here

12-01 13:51:12.220: E/WindowManager(14101): android.view.WindowLeaked: Activity com.decent.decentdialog.MainActivity has leaked window com.android.internal.policy.PhoneWindow$DecorView{b414dcc V.E...... R....... 0,0-1026,450} that was originally added here
12-01 13:51:12.220: E/WindowManager(14101): at android.view.ViewRootImpl.<init>(ViewRootImpl.java:368)
12-01 13:51:12.220: E/WindowManager(14101): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:299)
12-01 13:51:12.220: E/WindowManager(14101): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
12-01 13:51:12.220: E/WindowManager(14101): at android.app.Dialog.show(Dialog.java:319)
12-01 13:51:12.220: E/WindowManager(14101): at com.decent.decentdialog.MainActivity.onClick(MainActivity.java:38)
12-01 13:51:12.220: E/WindowManager(14101): at android.view.View.performClick(View.java:5198)
12-01 13:51:12.220: E/WindowManager(14101): at android.view.View$PerformClick.run(View.java:21147)
12-01 13:51:12.220: E/WindowManager(14101): at android.os.Handler.handleCallback(Handler.java:739)
12-01 13:51:12.220: E/WindowManager(14101): at android.os.Handler.dispatchMessage(Handler.java:95)
12-01 13:51:12.220: E/WindowManager(14101): at android.os.Looper.loop(Looper.java:148)
12-01 13:51:12.220: E/WindowManager(14101): at android.app.ActivityThread.main(ActivityThread.java:5417)
12-01 13:51:12.220: E/WindowManager(14101): at java.lang.reflect.Method.invoke(Native Method)
12-01 13:51:12.220: E/WindowManager(14101): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
12-01 13:51:12.220: E/WindowManager(14101): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
12-01 13:51:12.225: E/Surface(14101): getSlotFromBufferLocked: unknown buffer: 0xab4bdd90
12-01 13:51:12.243: D/INFO(14101): canceled()

解决方法

1、对于not attached to window manager,需要在show(),dismiss(),cancel的时候判断一下当前activity的状态

在你认为有可能在activity finish之后可能操作dialog的地方对contex添加一个状态的判断,如果状态正确才操作它。这个isFinishing()在用户没有调用finish()或者这个activty没有开始finish流程的时候一直返回false,之后一直返回true.

if(!mContext.isFinishing()){
     mDilaog.cancel();
}

在4.2之后有新加一个isDestroyed判断是否已经destory了也可以,两者在时间点上有一点点差别,个人认为isFinish就可以保证不会出异常了

if(!mContext.isDestroyed()){
     mDilaog.cancel();
}

2、对于Activity xxxx has leaked,that was originally added here

那就需要在onDestory()里面增加调用cancel,因为activity在destory的时候它对应的windowManager回去看当前还有没有view绑定在上面,发现了这个dialog还在绑定在上面就会报错。

1 @Override
2 public void onDestroy(){
3     super.onDestroy();
4     if ( mDialog!=null && mDialog.isShowing() ){
5         mDialog.cancel();
6     }
7 }

优质内容筛选与推荐>>
1、Oracle 游标
2、python3.7安装, 解决pip is configured with locations that require TLS/SSL问题
3、docker入门
4、用WinDbg探索CLR世界 [2] 线程
5、蓝桥杯 历届试题 大臣的旅费


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn