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完,于是就产生了所谓的窗体泄露。说到这里,我想大家也能明白这两个方法的区别了。
@Override
public void onDestroy() {
super.onDestroy();
if (mWindowManager != null) {
mWindowManager.removeViewImmediate(mDialogText);
}
}