Activity 已泄露窗口 - Android

Posted

技术标签:

【中文标题】Activity 已泄露窗口 - Android【英文标题】:Activity has leaked window - Android 【发布时间】:2014-03-16 02:07:17 【问题描述】:

看看这些代码:

Custom views and window attributes on android

问题

当我点击“主页按钮”时,exception 被抛出:Activity has leaked window... from this line:

localWindowManager.addView(colourView, layoutParams);

问题

你知道是什么原因造成的吗?

当我使用后退按钮关闭应用程序时,问题不会发生。

异常/错误日志

W/InputManagerService(   96): Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy@40908148 (uid=10056 pid=1368)
D/CordovaActivity( 1368): CordovaActivity.onDestroy()
D/CordovaWebView( 1368): >>> loadUrlNow()
E/WindowManager( 1368): Activity com.phonegap.helloworld.HelloWorld has leaked window pl.edu.uj.tcs.student.xxx.Display$Layer@40589368 that was originally added here
E/WindowManager( 1368): android.view.WindowLeaked: Activity com.phonegap.helloworld.HelloWorld has leaked window pl.edu.uj.tcs.student.xxx.Display$Layer@40589368 that was originally added here
E/WindowManager( 1368):         at android.view.ViewRoot.<init>(ViewRoot.java:258)
E/WindowManager( 1368):         at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
E/WindowManager( 1368):         at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
E/WindowManager( 1368):         at android.view.Window$LocalWindowManager.addView(Window.java:424)
E/WindowManager( 1368):         at pl.edu.uj.tcs.student.xxx.Display.setColorsViews(Display.java:181)
E/WindowManager( 1368):         at pl.edu.uj.tcs.student.xxx.Display$3.run(Display.java:139)
E/WindowManager( 1368):         at android.os.Handler.handleCallback(Handler.java:587)
E/WindowManager( 1368):         at android.os.Handler.dispatchMessage(Handler.java:92)
E/WindowManager( 1368):         at android.os.Looper.loop(Looper.java:130)
E/WindowManager( 1368):         at android.app.ActivityThread.main(ActivityThread.java:3683)
E/WindowManager( 1368):         at java.lang.reflect.Method.invokeNative(NativeMethod)
E/WindowManager( 1368):         at java.lang.reflect.Method.invoke(Method.java:507)
E/WindowManager( 1368):         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
E/WindowManager( 1368):         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
E/WindowManager( 1368):         at dalvik.system.NativeStart.main(Native Method)

D/CordovaActivity( 1368): onMessage(onPageStarted,about:blank)
D/CordovaWebViewClient( 1368): onPageFinished(about:blank)
D/CordovaActivity( 1368): onMessage(onPageFinished,about:blank)
D/CordovaActivity( 1368): onMessage(exit,null)
I/power   (   96): *** set_screen_state 0

编辑:

如何在 Cordova Activity 中向 onPause()、onStop() 等函数添加内容?

编辑 2:

为什么会有这样的问题?因为我创建的只是扩展 CordovaPlugin 的类和小型辅助类。就这样。我无法(我想)修改 Activity 类主体。我所能做的就是通过调用cordova.getActivity() 函数来获取它的引用。

【问题讨论】:

请附上来自 Logcat 的完整堆栈跟踪。 【参考方案1】:

什么是编程泄漏?

您获取但未释放的内存会导致内存泄漏。(窗口/对话框)也会发生类似情况。

这里发生了什么?

您正在尝试添加一个窗口,当它显示时它位于前台,但是当您按下主页按钮时,它会暂停然后停止(尝试在 onStop() 和 onPause() )。

由于您没有告诉系统删除​​您的视图,因此它仍然连接到现在已经从应用程序中消失/分离的窗口。因此,根据系统,您的 customView 占用了它没有释放的空间。

解决方案

在您的onStop() or onPause()andonDestroy() 中,确保关闭您的视图(dismiss(),如果它是一个对话框)或删除它(remove()如果使用窗口管理器添加)。

在您的卸载功能中添加关闭或删除功能,正如您提到的,在按下返回按钮时您会收到此错误。退出应用程序时,它的 onUnload() 方法会被调用。

建议(如果不在上下文中,则忽略)

据我观察,您正在尝试创建一个系统警报窗口,该窗口会覆盖其下方的任何内容。在活动中添加此类弹出窗口是有风险的,因为它可能会导致泄漏问题。 您实际上可以通过Service 添加此类窗口,这样它的寿命就会超过您的活动并显示在设备上的任何位置(如果您需要的话)。

Check this out

更新 2-Cordova 生命周期

你为什么不尝试在你的 CordovaPlugin 类中覆盖 onUnload 方法。我试图找到但docs 提到存在 onPause 和 onResume 方法。如果你在 CordovaPlugin 类中得到 onUnload 则删除你的视图在您的视图类中制作 runOnUiThread 方法。

【讨论】:

无意冒犯,但我不明白您的编辑说明。这对我来说似乎模棱两可。请更具体,以便我可以轻松帮助您。 你能发布完整的活动代码和cordova类 github.com/mrfesol/DisplayPlugin/blob/master/src/pl/edu/uj/tcs/… 为什么不尝试在您的 CordovaPlugin 类中覆盖 onUnload 方法。我尝试查找,但文档提到存在 onPause 和 onResume 方法。如果您在 CordovaPlugin 类中获得了 onUnload,则删除在视图类 runOnUiThread 方法中创建的视图。 哦,之前没注意。谢谢你。如果您在接下来的 15 小时内发布答案,您将获得赏金。【参考方案2】:

您尝试在退出 Activity 后显示Dialog

解决方案是在退出Activity 之前在您创建的Dialog 上调用dismiss(),例如在 onPause() 中。在离开Activity之前,应关闭所有窗口和对话框。

@Override
 protected void onStop() 
  super.onStop();
  if (loadingDlg != null) 
   loadingDlg.dismiss();
   loadingDlg = null;
  

希望对你有所帮助。

Activity-has-leaked-window-that-was-originally-added

【讨论】:

为了记录,我以前遇到过这个问题。由于通过回调显示对话框的时间,除了在尝试显示对话框并压制它时捕获异常之外,您可能无能为力(除非您想尝试将所有回调与活动)。 github.com/mrfesol/DisplayPlugin/blob/master/src/pl/edu/uj/tcs/…【参考方案3】:

检查对话框是否显示天气

@Override
  protected void onStop() 
    super.onStop();
if (loadingDlg != null) 

        if(loadingDlg.isShowing())
        loadingDlg.dismiss();

        loadingDlg = null;
 

【讨论】:

【参考方案4】:

泄漏的窗口通常发生在您的上下文显示对话框并且该上下文突然被强制关闭而您的对话框没有被正确关闭时。

为了解决这个问题,您必须在窗口泄漏错误之前修复您的错误。

【讨论】:

【参考方案5】:

在调用 AlertDialog 之前,我有一个名为 place 的 finish(),导致 Activity 在调用 AlertDialog 之前完成。我删除了 finish() 并在用户使用 AlertDialog 完成输入并修复了窗口泄漏后将其放置。

【讨论】:

以上是关于Activity 已泄露窗口 - Android的主要内容,如果未能解决你的问题,请参考以下文章

ProgressDialog.show() - Activity 已泄露窗口

“Activity 已经泄露了原本添加在这里的窗口”

android 活动已泄露窗口 com.android.internal.policy.impl.phonewindow$decorview 问题

Android Activity——启动过程探索

Android Activity——启动过程探索

Android Activity——启动过程探索