Android WindowManager 窗口泄漏的解决记录

来源:互联网 发布:mac如何运行java程序 编辑:程序博客网 时间:2024/05/17 05:16

12-13 17:05:58.037 27429-27429/com.android E/WindowManager: android.view.WindowLeaked: Activity com..android.ui.MainActivity has leaked window android.widget.TextView{42dd1c38 I.ED.... ......I. 0,0-140,155} that was originally added here                                                                                            at android.view.ViewRootImpl.<init>(ViewRootImpl.java:368)                                                                                            at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:249)                                                                                            at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)                                                                                            at com.iwoncloud.familyface.client.android.ui.contacts.fragment.ContactsFragment.onCreateView(ContactsFragment.java:71)                                                                                            at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974)                                                                                            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)                                                                                            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)                                                                                            at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742)                                                                                            at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)                                                                                            at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)                                                                                            at android.os.Handler.handleCallback(Handler.java:733)                                                                                            at android.os.Handler.dispatchMessage(Handler.java:95)                                                                                            at android.os.Looper.loop(Looper.java:136)                                                                                            at android.app.ActivityThread.main(ActivityThread.java:5111)                                                                                            at java.lang.reflect.Method.invokeNative(Native Method)                                                                                            at java.lang.reflect.Method.invoke(Method.java:515)                                                                                            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)                                                                                            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)

                                                                                            at dalvik.system.NativeStart.main(Native Method)

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

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

2.还有一种情况就是下面代码,来创建窗口渲染的时候(本人遇到这种情况)

我们在做UI相关的代码时有时候会碰到WindowLeak,也就是所谓的窗体泄露,泄露的原因是因为androidUI操作在主线程中操作,但是我们会需要在一些线程或者异步任务中操作UI界面元素的需求,那么这个时候可能会出现类似问题。我在做浮动窗口的时候碰到了这个问题,浮动窗口需要用到WindowManager,windowManger又是一个activity的一个变量,它依存于Activity,当横竖屏切换或者activity销毁的时候这个变量会销毁。销毁的时候导致windowmanager通过AddView()方法添加的View没有依存,导致窗体泄露。那么问题来了,为什么这里会泄露了?

TextView mDialogText = (TextView) LayoutInflater.from(getActivity()).inflate(R.layout.list_position, null);
WindowManager mWindowManager = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
mWindowManager.addView(mDialogText,lp);


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

2.解决方法:在onDestroy()里面调用了removeView方法,想要避免窗体泄露,但是这个方法并不管用,后来换成removeViewImmediate()就解决了这个问题,原因就是两个方法设计到线程同步问题,removeViewImmediate()是通知View立刻调用View.onDetachWindow(),这说明这个方法是通过一个监听或者观察者来实现的,因为线程的同步跟异步问题导致activity销毁了,但view还没有被remove完,于是就产生了所谓的窗体泄露。说到这里,我想大家也能明白这两个方法的区别了。


@Overridepublic void onDestroy() {    super.onDestroy();    if (mWindowManager != null) {        mWindowManager.removeViewImmediate(mDialogText);    }}








android 


WindowManager


removeView(View v)


removeViewImmediate(View v)的区别

1 0
原创粉丝点击