Android中View not attached to window manager错误,android.view.WindowLeaked的解决方案

原因基本都是Dismiss对话框的时候,Activity已经不再存在。

常发生这类Exception的情形都是,有一个费时的线程操作,需要在显示一个Dialog,在任务开始的时候显示一个对话框,然后当任务完成了再Dismiss对话框,如果在此期间如果Activity因为某种原因被杀掉且又重新启动了,那么当Dialog调用Dismiss的时候WindowManager检查发现Dialog所属的Activity已经不存在了,所以会报java.lang.IllegalArgumentException: View not attached to window manager

其实此类Exception的一重要的原因是,Dialog的创建显示和取消都允许在非UI线程中进程。在Android当中非UI线程是不允许操作UI相关的事情,比如添加移除View等,但是为会么允许创建显示和取消对话框呢?而且还有可能引发此Exception导致应用Crash。

要想避免此类Exception,就要正确的使用对话框,也要正确的使用线程。

正确的使用对话框

不要在非UI线程中使用对话框创建,显示和取消对话框。
那么对于异步操作显示对话框怎么办呢?Activity都有相应的操作对话框的回调比如onCreateDialog(),showDialog(),dimissDialog(),removeDialog()等等。这些因为都是Activity的方法,所以用起来更方便,也不用显示创建和操控Dialog对象,一切都由框架操控,相对来说比较安全。
另外就是一定要让对话框对象在Activity的可控制范围之内和生命周期之内,比如一定要是它的成员变量,并且在让对话框变量活跃在Activity的onCreate()和onDestroy()之间。

正确的使用线程

尽量少用单独线程,除非是真正的费时操作才用线程,线程也不要直接用Java式的匿名线程,除非是那种单纯的操作,操作完成后不需要做其他事情的。
尽可能多用Android提供的类比如AsyncTask等。另外如果线程操作过程中还需要与主线程有交互,那么最好保存一个线程的对象,并且线程内部最有一定的控制,这样可以让Activity更好的操控线程。
如果说某些操作是特别费时的,且是经常性的操作,比如从网络获取数据,或是从后台读取文件,或是导入/导出,恢复/备份的事情,最好放到后台Service中去做,然后在StatusBar中给出相应进度。


虽然是小问题一个,但也困扰了我一段时间,现在记下来,给自己做个备忘,也可以给其他人一个参考

  1. 01-08 01:49:27.874: ERROR/WindowManager(473): Activity com.photos.MainActivity has leaked window android.widget.ImageButton@43e40d10 that was originally added here  
  2. 01-08 01:49:27.874: ERROR/WindowManager(473): android.view.WindowLeaked: Activity com.photos.MainActivity has leaked window android.widget.ImageButton@43e40d10 that was originally added here  
  3. 01-08 01:49:27.874: ERROR/WindowManager(473):     at android.view.ViewRoot.<init>(ViewRoot.java:247)  
  4. 01-08 01:49:27.874: ERROR/WindowManager(473):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)  
  5. 01-08 01:49:27.874: ERROR/WindowManager(473):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)  
  6. 01-08 01:49:27.874: ERROR/WindowManager(473):     at android.view.Window$LocalWindowManager.addView(Window.java:424)  
  7. 01-08 01:49:27.874: ERROR/WindowManager(473):     at android.widget.PopupWindow.invokePopup(PopupWindow.java:828)  
  8. 01-08 01:49:27.874: ERROR/WindowManager(473):     at android.widget.PopupWindow.showAtLocation(PopupWindow.java:688)  
  9. 01-08 01:49:27.874: ERROR/WindowManager(473):     at com.photos.MainActivity.showCommonPopup(MainActivity.java:256)  
  10. 01-08 01:49:27.874: ERROR/WindowManager(473):     at com.photos.MainActivity.access$3(MainActivity.java:255)  
  11. 01-08 01:49:27.874: ERROR/WindowManager(473):     at com.photos.MainActivity$2.handleMessage(MainActivity.java:88)  
  12. 01-08 01:49:27.874: ERROR/WindowManager(473):     at android.os.Handler.dispatchMessage(Handler.java:99)  
  13. 01-08 01:49:27.874: ERROR/WindowManager(473):     at android.os.Looper.loop(Looper.java:123)  
  14. 01-08 01:49:27.874: ERROR/WindowManager(473):     at android.app.ActivityThread.main(ActivityThread.java:4627)  
  15. 01-08 01:49:27.874: ERROR/WindowManager(473):     at java.lang.reflect.Method.invokeNative(Native Method)  
  16. 01-08 01:49:27.874: ERROR/WindowManager(473):     at java.lang.reflect.Method.invoke(Method.java:521)  
  17. 01-08 01:49:27.874: ERROR/WindowManager(473):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)  
  18. 01-08 01:49:27.874: ERROR/WindowManager(473):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)  
  19. 01-08 01:49:27.874: ERROR/WindowManager(473):     at dalvik.system.NativeStart.main(Native Method)  
 

按字面了解,Window Leaked大概就是说一个窗体泄漏了,也就是我们常说的内存泄漏,为什么窗体会泄漏呢?

产生原因:
我们知道Android的每一个Activity都有个WindowManager窗体管理器,同样,构建在某个Activity之上的对话框、PopupWindow也有相应的WindowManager窗体管理器。因为对话框、PopupWindown不能脱离Activity而单独存在着,所以当某个Dialog或者某个PopupWindow正在显示的时候我们去finish()了承载该Dialog(或PopupWindow)的Activity时,就会抛Window Leaked异常了,因为这个Dialog(或PopupWindow)的WindowManager已经没有谁可以附属了,所以它的窗体管理器已经泄漏了。


解决方法:
关闭(finish)某个Activity前,要确保附属在上面的Dialog或PopupWindow已经关闭(dismiss)了。

转载自:http://www.xuebuyuan.com/1585505.html

http://blog.csdn.net/u_xtian/article/details/6123945

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值