Android 活动已泄漏窗口/对话框(再次泄漏!)

Android 活动已泄漏窗口/对话框(再次泄漏!),android,android-activity,dialog,window,memory-leaks,Android,Android Activity,Dialog,Window,Memory Leaks,是的,我读过无数关于同一个问题的问题 我的代码很简单:我只需在onCreate上使用showDialog(int-id),然后旋转设备代码就是这样(测试用例),这就足以引起问题。据我所知,showDialog的方法将解决这个问题。。。对话框将消失,然后在更改后调用onCreate,并干净地再次显示对话框。但是没有。这个推理有什么不对吗? 我(想我)明白,但我不知道如何解决这个问题。即使iosched应用程序在实现EULA窗口时也存在同样的问题(更改EULA对话框上的方向,您就会发现漏洞)。我读过

是的,我读过无数关于同一个问题的问题

我的代码很简单:我只需在
onCreate
上使用
showDialog(int-id)
,然后旋转设备代码就是这样(测试用例),这就足以引起问题。据我所知,
showDialog
的方法将解决这个问题。。。对话框将消失,然后在更改后调用
onCreate
,并干净地再次显示对话框。但是没有。这个推理有什么不对吗?

我(想我)明白,但我不知道如何解决这个问题。即使iosched应用程序在实现EULA窗口时也存在同样的问题(更改EULA对话框上的方向,您就会发现漏洞)。我读过关于在onPause上取消对话框的内容,但1)如果对话框尚未显示,我可能会取消,2)跟踪对话框似乎工作量太大。必须有一个更稳健的方法

所以。。。处理这个问题需要什么更干净的代码

多谢各位


日志错误输出:

01-30 00:27:18.615: E/WindowManager(20316): Activity com.test.PreSetupActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@418e0c28 that was originally added here
01-30 00:27:18.615: E/WindowManager(20316): android.view.WindowLeaked: Activity com.test.PreSetupActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@418e0c28 that was originally added here
01-30 00:27:18.615: E/WindowManager(20316):     at android.view.ViewRootImpl.<init>(ViewRootImpl.java:343)
01-30 00:27:18.615: E/WindowManager(20316):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:245)
01-30 00:27:18.615: E/WindowManager(20316):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:193)
01-30 00:27:18.615: E/WindowManager(20316):     at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:118)
01-30 00:27:18.615: E/WindowManager(20316):     at android.view.Window$LocalWindowManager.addView(Window.java:537)
01-30 00:27:18.615: E/WindowManager(20316):     at android.app.Dialog.show(Dialog.java:274)
01-30 00:27:18.615: E/WindowManager(20316):     at com.test.PreSetupActivity.onCreate(PreSetupActivity.java:88)
01-30 00:27:18.615: E/WindowManager(20316):     at android.app.Activity.performCreate(Activity.java:4465)
01-30 00:27:18.615: E/WindowManager(20316):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
01-30 00:27:18.615: E/WindowManager(20316):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919)
01-30 00:27:18.615: E/WindowManager(20316):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980)
01-30 00:27:18.615: E/WindowManager(20316):     at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3347)
01-30 00:27:18.615: E/WindowManager(20316):     at android.app.ActivityThread.access$700(ActivityThread.java:122)
01-30 00:27:18.615: E/WindowManager(20316):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1150)
01-30 00:27:18.615: E/WindowManager(20316):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-30 00:27:18.615: E/WindowManager(20316):     at android.os.Looper.loop(Looper.java:137)
01-30 00:27:18.615: E/WindowManager(20316):     at android.app.ActivityThread.main(ActivityThread.java:4340)
01-30 00:27:18.615: E/WindowManager(20316):     at java.lang.reflect.Method.invokeNative(Native Method)
01-30 00:27:18.615: E/WindowManager(20316):     at java.lang.reflect.Method.invoke(Method.java:511)
01-30 00:27:18.615: E/WindowManager(20316):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-30 00:27:18.615: E/WindowManager(20316):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-30 00:27:18.615: E/WindowManager(20316):     at dalvik.system.NativeStart.main(Native Method)
01-30 00:27:18.615:E/WindowManager(20316):Activity com.test.PreSetupActivity已泄漏window com.android.internal.policy.impl.PhoneWindow$DecorView@418e0c28原来是加在这里的
01-30 00:27:18.615:E/WindowManager(20316):android.view.WindowLeaked:Activity com.test.PreSetupActivity已泄漏window com.android.internal.policy.impl.PhoneWindow$DecorView@418e0c28原来是加在这里的
01-30 00:27:18.615:E/WindowManager(20316):在android.view.ViewRootImpl。(ViewRootImpl.java:343)
01-30 00:27:18.615:E/WindowManager(20316):在android.view.WindowManagerImpl.addView(WindowManagerImpl.java:245)
01-30 00:27:18.615:E/WindowManager(20316):在android.view.WindowManagerImpl.addView(WindowManagerImpl.java:193)
01-30 00:27:18.615:E/WindowManager(20316):在android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:118)
01-30 00:27:18.615:E/WindowManager(20316):在android.view.Window$LocalWindowManager.addView(Window.java:537)
01-30 00:27:18.615:E/WindowManager(20316):在android.app.Dialog.show(Dialog.java:274)
01-30 00:27:18.615:E/WindowManager(20316):位于com.test.PreSetupActivity.onCreate(PreSetupActivity.java:88)
01-30 00:27:18.615:E/WindowManager(20316):位于android.app.Activity.performCreate(Activity.java:4465)
01-30 00:27:18.615:E/WindowManager(20316):位于android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
01-30 00:27:18.615:E/WindowManager(20316):在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919)
01-30 00:27:18.615:E/WindowManager(20316):在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980)
01-30 00:27:18.615:E/WindowManager(20316):在android.app.ActivityThread.handleRunchActivity(ActivityThread.java:3347)
01-30 00:27:18.615:E/WindowManager(20316):在android.app.ActivityThread.access$700(ActivityThread.java:122)
01-30 00:27:18.615:E/WindowManager(20316):在android.app.ActivityThread$H.handleMessage(ActivityThread.java:1150)
01-30 00:27:18.615:E/WindowManager(20316):位于android.os.Handler.dispatchMessage(Handler.java:99)
01-30 00:27:18.615:E/WindowManager(20316):位于android.os.Looper.loop(Looper.java:137)
01-30 00:27:18.615:E/WindowManager(20316):位于android.app.ActivityThread.main(ActivityThread.java:4340)
01-30 00:27:18.615:E/WindowManager(20316):位于java.lang.reflect.Method.Invokenactive(本机方法)
01-30 00:27:18.615:E/WindowManager(20316):位于java.lang.reflect.Method.invoke(Method.java:511)
01-30 00:27:18.615:E/WindowManager(20316):位于com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-30 00:27:18.615:E/WindowManager(20316):位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-30 00:27:18.615:E/WindowManager(20316):在dalvik.system.NativeStart.main(本机方法)

有一个内部类,充当您的状态持有者,其中有一个布尔字段,用于指示对话框是否显示。使用
onretainonconfigurationinstance
跟踪跨方向的更改,只需重新显示
onResume

下面是一些代码+伪代码:

public class ProfileActivity extends Activity {
  private StateHolder mStateHolder;
  private Dialog dialog;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Object retained = getLastNonConfigurationInstance();
    if (retained != null && retained instanceof StateHolder) {
      mStateHolder = (StateHolder) retained;
    } else {
      mStateHolder = new StateHolder();
    }
  }

  @Override
  public Object onRetainNonConfigurationInstance() {
    return mStateHolder;
  }

  @Override
  public void onPause() {
    super.onPause();
    if(dialog != null && dialog.isShowing()) {
      dialog.dismiss();
    }
  }

  @Override
  public void onResume() {
    if(mStateHolder.mIsShowingDialog) {
      dialog.show();
    }
  }

  private void showDialog() {
    mStateHolder.mIsShowingDialog = true;
    dialog.show();
  }

  private static class StateHolder {
    boolean mIsShowingDialog;
    public StateHolder() {}
  }

}

我看到一些人在跟踪窗口,基本上是在不使用
showDialog
方法的情况下创建它们,并检查它们是否显示(
isShowing()
),然后相应地关闭(在顶部/暂停时)。然而,我相信这是一个安全的猜测,自动方式(showDialog)应该更干净、更简单,对吗?您可以在onPostexecute()中关闭对话框,比如dialog.dismise();我会选择DialogFragment。“它自动管理旋转,因此更加优雅。”WindRider当然可以。我很久以前就离开了showDialog基础设施。这个问题涉及到我仍然拥有的支持API3(!!!)的遗留代码,这让我觉得它毫无用处。我很高兴它已经被弃用很长很长时间了。我会疯狂地将它用于任何已经可以通过兼容包使用片段的东西。好家伙!嗯,不幸的是,我说服自己,
showDialog
只是一个PITA(对不起)。我将尝试有关手动对话框的此解决方案,并将向您报告。非常感谢。再次感谢你。我使用上述概念,它的工作完美!我甚至在emulator中非常快速地反复按Ctrl+F11,每秒更改两次方向,多次。。。这是普通手机用户永远不会做的事情。我的日志线尽可能的干净。非常感谢,因为这让我昨天损失了不少时间。回答得很好,我使用了
onPause()
同样的方法处理片段。使用
setretains