使用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 }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM