AlertDialog的show()方法导致Activity泄漏窗口。

32

由于使用了 AlertDialog,我在运行时遇到了窗口泄漏错误。

下面的代码中,我已经标出了引起错误的行:

堆栈跟踪:

08-18 02:48:04.489  28893-28893/? E/WindowManagerActivity com.ms.ha.fragment.FirstActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{52e58540 V.E..... R.....ID 0,0-1026,585} that was originally added here
    android.view.WindowLeaked: Activity com.ms.ha.fragment.FirstActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{52e58540 V.E..... R.....ID 0,0-1026,585} that was originally added here
            at android.view.ViewRootImpl.<init>(ViewRootImpl.java:345)
            at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:239)
            at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
            at android.app.Dialog.show(Dialog.java:281)
            at com.ms.ha.fragment.TourGuideLoadURLFragment$WebAppInterface.moveToNextScreen(TourGuideLoadURLFragment.java:116)
            at android.webkit.WebViewCore.nativeMouseClick(Native Method)
            at android.webkit.WebViewCore.nativeMouseClick(Native Method)
            at android.webkit.WebViewCore.access$6800(WebViewCore.java:59)
            at android.webkit.WebViewCore$EventHub.dispatchWebKitEvent(WebViewCore.java:1793)
            at android.webkit.WebViewInputDispatcher.dispatchWebKitEvent(WebViewInputDispatcher.java:689)
            at android.webkit.WebViewInputDispatcher.dispatchWebKitEvents(WebViewInputDispatcher.java:639)
            at android.webkit.WebViewInputDispatcher.access$800(WebViewInputDispatcher.java:78)
            at android.webkit.WebViewInputDispatcher$WebKitHandler.handleMessage(WebViewInputDispatcher.java:1153)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.webkit.WebViewCore$WebCoreThread.run(WebViewCore.java:814)
            at java.lang.Thread.run(Thread.java:841)

FirstActivity.java:

 public class FirstActivity extends FragmentActivity  implements View.OnClickListener{

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.fragment_tour_guide_web);
  .......
  .......

   webView.addJavascriptInterface(new WebAppInterface(this), "Android");

 }


    public class WebAppInterface {
        Context mContext;

        /**
         * Instantiate the interface and set the context
         */
        WebAppInterface(Context c) {
            mContext = c;
        }

        /**
         * Intent - Move to next screen
         */

        @JavascriptInterface
        public void moveToNextScreen() {
            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                    context);

            // set title
            alertDialogBuilder.setTitle("Your Title");

            // set dialog message
            alertDialogBuilder
                    .setMessage("Click yes!")
                    .setCancelable(false)
                    .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {

                            Intent i = new Intent(FirstActivity.this,SecondActivity.class);
                            startActivity(i);
                        }
                    })
                    .setNegativeButton("No", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            // if this button is clicked, just close
                            // the dialog box and do nothing
                            dialog.cancel();
                        }
                    });

            // create alert dialog
            AlertDialog alertDialog = alertDialogBuilder.create();

            // show it
            alertDialog.show();  --->leak window error

        }

    }

  }

我不知道如何解决这个问题。


1
请查看此链接:https://dev59.com/v3E85IYBdhLWcg3wSxcv - Beena
2
当您尝试在一个活动中创建和显示AlertDialog,并在另一个活动中关闭时,会发生此错误。 - Logic
6个回答

60

你之所以遇到错误,是因为在你的Activity被销毁时,ProgressDialog仍在运行。在启动新的Activity之前,你应该关闭对话框。

.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
  public void onClick(DialogInterface dialog, int id) {
      if (alertDialog != null && alertDialog.isShowing()) {
          alertDialog.dismiss();
      }
      Intent i = new Intent(FirstActivity.this, SecondActivity.class);
      startActivity(i);
  }
});

希望这有所帮助!


尝试使用我在答案中编辑的代码。当新活动开始时,关闭对话框或完成活动。 - Rajesh Jadav
这意味着您的主线程不知道您所做的更改,当它采取行动时,您的主线程发现它已经是不同的对象了。 尝试在主线程中调用您的函数。 runOnUiThread(new Runnable() { @Override public void run() { //your function } }); - Jevgenij Kononov
但是在这种情况下,堆栈跟踪应该会泄漏到 onStop()onDestroy(),不是吗? - kAmol

16

在onPause()方法中关闭alertDialog,即调用alertDialog.dismiss()。

注意:如果在Activity结束之前未关闭对话框,通常会发生WindowLeaked异常。


5

如果您在尝试显示对话框时不在UI线程中,也会出现WindowLeaked异常。 简单的修复方法:

this.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        // show dialog here
    }
});

3

在Activity结束之前,您必须需要解除/取消对话框。如果在Activity终止之前未解除对话框,则通常会发生这种情况。


-12
请在清单文件中检查是否已设置了Internet权限:
<uses-permission android:name="android.permission.INTERNET" />

-14

我不知道这是否有帮助,但在我的问题中,多dex引起了问题。 在build.gradle文件中。

multiDexEnabled false

3
不,这里不适用多dex! =0 - Jorgesys

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接