对话框显示时,android非法异常

时间:2015-07-08 11:40:52

标签: android android-alertdialog

我有崩溃日志:

java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{21f9ba68 V.E..... R.....ID 0,0-1136,402} not attached to window manager
at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:402)
at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:328)
at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:84)
at android.app.Dialog.dismissDialog(Dialog.java:433)
at android.app.Dialog.dismiss(Dialog.java:416)
at ys.a(ConfirmationDialog.java:82)
at ys.a(ConfirmationDialog.java:76)
at **com.smarttech.kapp.SnapshotActivity.onOptionsItemSelected(SnapshotActivity.java:147)**
at android.app.Activity.onMenuItemSelected(Activity.java:3036)
at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:373)
at com.android.internal.policy.impl.PhoneWindow.onMenuItemSelected(PhoneWindow.java:1222)
at com.android.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:761)
at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:155)
at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:904)
at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:894)
at android.widget.ActionMenuView.invokeItem(ActionMenuView.java:611)
at com.android.internal.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:197)
at android.view.View.performClick(View.java:5217)
at android.view.View.onKeyUp(View.java:9663)
at android.widget.TextView.onKeyUp(TextView.java:7047)
at android.view.KeyEvent.dispatch(KeyEvent.java:3171)
at android.view.View.dispatchKeyEvent(View.java:8876)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1695)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1695)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1695)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1695)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1695)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:2671)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1787)
at android.app.Activity.dispatchKeyEvent(Activity.java:2837)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2549)
at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4661)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4616)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4174)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4227)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4193)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4303)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4201)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4360)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4174)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4227)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4193)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4201)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4174)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4227)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4193)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4336)
at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:4500)
at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2607)
at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:2201)
at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:2192)
at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2584)
at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:143)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:6117)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

这是在快照活动中显示对话框的代码:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            finish();
            return true;
        case R.id.snapshot_delete:
            Log.d(TAG, "delete snapshot");
            **delete();**
            return true;
        case R.id.snapshot_share:
            export();
            return true;
    }

    return super.onOptionsItemSelected(item);
}

private void delete() {
    Log.d(TAG, "Delete snapshot");
    final int index = pager.getCurrentItem();
    ConfirmationDialog.prompt(this, R.string.delete_snapshot, R.string.delete_snapshot_confirmation, R.string.delete, android.R.string.cancel, new Runnable() {
        @Override
        public void run() {
            snapshots.get(index).delete();
            loadSnapshots();
        }
    });
}

这次崩溃非常难以重现,而且所有信息都是我所拥有的。 这个例外的原因是什么? 它是如何修复的? 我认为原因是对话中的线程,但我不确定

public static void prompt(final Context context, int titleResourceId, int questionResourceId, int positiveButton, int negativeButton, final Runnable confirmedRunnable, final Runnable cancelledRunnable) {
    closeDialog();
    DialogInterface.OnClickListener confirmed = new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            currentDialog = null;
            confirmedRunnable.run();
        }
    };
    DialogInterface.OnClickListener cancelled = new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            currentDialog = null;
            if (cancelledRunnable != null) {
                cancelledRunnable.run();
            }
        };
    };
    currentDialog = new AlertDialog.Builder(context).setTitle(titleResourceId).setMessage(questionResourceId).setIcon(android.R.drawable.ic_dialog_alert).setPositiveButton(positiveButton, confirmed)
            .setNegativeButton(negativeButton, cancelled).show();
    currentDialog.setCancelable(cancelled == null);
    currentDialog.setCanceledOnTouchOutside(cancelled == null);
}

这是promt实现

6 个答案:

答案 0 :(得分:19)

你的堆栈跟踪的最高级别告诉你出了什么问题:

java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{21f9ba68 V.E..... R.....ID 0,0-1136,402} not attached to window manager
at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:402)
at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:328)
at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:84)
at android.app.Dialog.dismissDialog(Dialog.java:433)
at android.app.Dialog.dismiss(Dialog.java:416)

您正在调用当前未再显示的对话框。 如下所示:当您调用dismiss时,您的Activity / Fragment可能已被销毁( - >"未附加到窗口管理器")。

[edit]解决这个问题的一种方法是检查activity.isFinishing()或fragment.isAdded()

答案 1 :(得分:4)

请解雇如下

if ((alertDialog != null) && alertDialog.isShowing())
        {
            alertDialog.dismiss();
        }

答案 2 :(得分:1)

安全地关闭对话框的一种简单方法是在尝试关闭对话框之前检查对话框所包含的视图当前是否显示。这看起来像:

if (view.isShown()) {
    dialog.dismiss()
}

答案 3 :(得分:1)

我认为没有理由为什么整个应用程序应该崩溃这样的事情。在我看来,此时的例外必须是活动已经结束或某事的结果。在任何一种情况下,我都猜测用户不再查看对话框,所以我已经做了一个简单的实用工具来静默关闭我的对话框。

import android.app.Dialog;
import android.util.Log;

import java.io.PrintWriter;
import java.io.StringWriter;

public class DialogUtil {

    public static final String TAG = "DialogUtil";

    public static void safeDismiss(Dialog dialog) {
        if (dialog != null && dialog.isShowing()) {
            try {
                dialog.dismiss();
            } catch (RuntimeException ex) {
                StringWriter sw = new StringWriter();
                ex.printStackTrace(new PrintWriter(sw));
                Log.e(TAG, sw.toString());
            }
        }
    }
}

答案 4 :(得分:0)

我建议,您还应该检查活动是否为空。

if (activity != null && progressDialog != null && progressDialog.isShowing()) {
                progressDialog.dismiss();
            }

答案 5 :(得分:0)

我有同样的问题, 我通过检查来解决这个问题:

if (alertDialog  != null && alertDialog .isShowing() && !this.isFinishing())
 {
  alertDialog .dismiss();
 }