关于Android中Dialog show跟dismiss时出现crash的解决办法

    最近在做项目的时候,越来越多的开发者反馈SDK Dialog的show以及dismiss导致程序crash,出现的问题是传递进来的Activity被finish或者重建(横竖屏切换)了。下面分别对这两种情况说明以及解决办法。

在Dialog.show时出现crash

日志信息:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 06-03 17:18:14.550: E/AndroidRuntime(12584): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@42963e08 is not valid; is your activity running?  
  2. 06-03 17:18:14.550: E/AndroidRuntime(12584):    at android.view.ViewRootImpl.setView(ViewRootImpl.java:587)  
  3. 06-03 17:18:14.550: E/AndroidRuntime(12584):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:326)  
  4. 06-03 17:18:14.550: E/AndroidRuntime(12584):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224)  
  5. 06-03 17:18:14.550: E/AndroidRuntime(12584):    at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149)  
  6. 06-03 17:18:14.550: E/AndroidRuntime(12584):    at android.view.Window$LocalWindowManager.addView(Window.java:561)  
  7. 06-03 17:18:14.550: E/AndroidRuntime(12584):    at android.app.Dialog.show(Dialog.java:293)  
  8. 06-03 17:18:14.550: E/AndroidRuntime(12584):    at com.umeng.socialize.controller.impl.m.onStart(SocialServiceImpl.java:1451)  
  9. 06-03 17:18:14.550: E/AndroidRuntime(12584):    at com.umeng.socialize.controller.impl.aa.onStart(SocialServiceImpl.java:2529)  
  10. 06-03 17:18:14.550: E/AndroidRuntime(12584):    at com.umeng.socialize.controller.impl.ab.onStart(SocialServiceImpl.java:2557)  
  11. 06-03 17:18:14.550: E/AndroidRuntime(12584):    at com.umeng.socialize.controller.impl.c.c(SocialServiceImpl.java:2594)  
  12. 06-03 17:18:14.550: E/AndroidRuntime(12584):    at com.umeng.socialize.controller.impl.c.doOauthVerify(SocialServiceImpl.java:2339)  
  13. 06-03 17:18:14.550: E/AndroidRuntime(12584):    at com.umeng.socialize.controller.impl.c.c(SocialServiceImpl.java:1456)  
  14. 06-03 17:18:14.550: E/AndroidRuntime(12584):    at com.umeng.socialize.controller.impl.c.postShare(SocialServiceImpl.java:1295)  
  15. 06-03 17:18:14.550: E/AndroidRuntime(12584):    ... 17 more  

我们知道所有的窗口创建和管理都是依附于window manager的,因此Dialog的创建也不例外。Dialog的创建流程通过查看源码可以知道,在Dialog的构造函数中,创建了一个Window对象,但我们知道Window对象并不是用于显示的,真正用于显示的是View对象。因此通过Dialog的show方法构造了一个mDecor的View对象,并最终通过WindowManager的addView()方法显示Dialog,如果此时你的activity应为某种原因被finish或者重建就会出现此问题。


解决办法:

在创建Dialog的时候,我们设置该dialog属于某个activity,这样我们根据Activity的状态决定是否显示Dialog.

创建Dialog时设置activity:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <pre name="code" class="java" style="color: rgb(51, 51, 51); font-size: 14px; line-height: 26px;">ProgressDialog <span style="font-family: 微软雅黑;">mDialog = new ProgressDialog(this);</span>  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family: 微软雅黑;">mDialog.setMessage("test");</span>  
mDialog.setCancelable(false);mDialog.setOwnerActivity(this);

 
显示Dialog的时候做相应地判断: 

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. if ( mDialog != null ) {  
  2.     Activity activity = mDialog.getOwnerActivity();  
  3.     if ( activity != null && !activity.isFinishing() ) {  
  4.         mDialog.show();  
  5.     }  
  6. }  

Dialog.dismiss时出现crash

日志信息:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 06-03 21:03:18.027: E/AndroidRuntime(6197): java.lang.IllegalArgumentException: View not attached to window manager  
  2. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:385)  
  3. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:287)  
  4. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:79)  
  5. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at android.app.Dialog.dismissDialog(Dialog.java:323)  
  6. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at android.app.Dialog.dismiss(Dialog.java:306)  
  7. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at com.umeng.soexample.MainActivity$1$1.onComplete(MainActivity.java:61)  
  8. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at com.umeng.socialize.qq.controller.impl.UMQQSsoHandler$4.onCancel(UMQQSsoHandler.java:355)  
  9. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at com.tencent.jsutil.PackIUiListener$1.handleMessage(ProGuard:29)  
  10. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at android.os.Handler.dispatchMessage(Handler.java:99)  
  11. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at android.os.Looper.loop(Looper.java:153)  
  12. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at android.app.ActivityThread.main(ActivityThread.java:5297)  
  13. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at java.lang.reflect.Method.invokeNative(Native Method)  
  14. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at java.lang.reflect.Method.invoke(Method.java:511)  
  15. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)  
  16. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)  
  17. 06-03 21:03:18.027: E/AndroidRuntime(6197):     at dalvik.system.NativeStart.main(Native Method)  
原因:Dialog在dismiss得时候是通过直接从WindowManager remove操作来完成的。当Activity被销毁后,此时的Dialog处于游离状态,在remove的时候会迭代,如果发现此View没有在数组mViews中时讲抛出IllegalArgumentException("View not attached to window manager")异常。

解决办法:

创建Dialog的时候设置该Dialog所属的Activity,在dismiss的时候根据此activity的状态来决定是否dismiss此dialog

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. if ( mDialog != null && mDialog.isShowing()) {  
  2.     Activity activity = mDialog.getOwnerActivity();  
  3.     if ( activity != null && !activity.isFinishing()) {  
  4.         mDialog.dismiss();      
  5.     }  
  6. }  


上面的方法适用于在非自己的Activity中显示Dialog的处理策略。对于自己的Activity可以直接根据Activity的生命周期方法对Dialog做相应的处理,比如在onDestroy时先dismiss此Dialog;同时可以使用Activity中对Dialog的相关回调来处理,比如Activity.showDialog方法,这样就将此Dialog跟Activity的生命周期方法关联起来了,在触发onDestroy的时候自动的先关闭目前属于此Activity且处于显示状态的所有Dialog。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值