Java android.view.WindowManager$BadTokenException在显示PopOver时出现异常

Java android.view.WindowManager$BadTokenException在显示PopOver时出现异常,java,android,android-fragments,android-activity,android-popupwindow,Java,Android,Android Fragments,Android Activity,Android Popupwindow,我添加了以下代码以在微调器视图上显示弹出框。代码使用自定义PopOver,它扩展了PopupWindow: @Override public void onStart() { super.onStart(); new Handler().postDelayed(new Runnable() { public void run() { if (mActivity ==

我添加了以下代码以在微调器视图上显示弹出框。代码使用自定义PopOver,它扩展了PopupWindow:

    @Override
    public void onStart() {
        super.onStart();

            new Handler().postDelayed(new Runnable() {
                public void run() {
                    if (mActivity == null || !isAdded() || mActivity.isFinishing() || mSpinner == null) {
                        return;
                    }

                    displayPopOver();
                }
            }, 500L); // have seen BadTokenException if we try to show the popup too early
     }


   private void displayPopOver() {
    //PopOver is a custom class that extends PopupWindow
    PopOver p = PopOver.createVerticalPopOver(mActivity, PopOver.Type.TIP);
    p.show(mSpinner);
   }
我无法重现崩溃,但通过崩溃报告,我看到应用程序多次崩溃。我做错了什么?在onResume而不是onStart中调用此代码是否可以帮助

android.view.WindowManager$BadTokenException:无法添加窗口- 令牌null无效;你的活动正在进行吗? 1位于android.view.ViewRootImpl.setViewRootImpl.java:532 2位于android.view.WindowManagerGlobal.addViewWindowManagerGlobal.java:259 3在android.view.WindowManagerImpl.addViewWindowManagerImpl.java:69 4位于android.widget.PopupWindow.invokePopupWindow.java:1019 5在android.widget.PopupWindow.showtLocationPopupWindow.java:850 6在android.widget.PopupWindow.showtLocationPopupWindow.java:814 7在com.PopOver.showPopOver.java:339 8位于com.MainFragment.displayPopOverMainFragment.java:515 9位于com.MainFragment.access$1300MainFragment.java:73 10位于com.MainFragment$5.runMainFragment.java:497 11位于android.os.Handler.handleCallbackHandler.java:733 12位于android.os.Handler.dispatchMessageHandler.java:95 13在android.os.Looper.Looper.java:136 14在android.app.ActivityThread.mainActivityThread.java:5001 15位于java.lang.reflect.Method.invokenactive方法 16位于java.lang.reflect.Method.invokeMethod.java:515 17位于com.android.internal.os.ZygoteInit$methodAndArgscaler.runZygoteInit.java:785 18位于com.android.internal.os.ZygoteInit.mainZygoteInit.java:601 19在dalvik.system.NativeStart.main本地方法


引发的异常表示您过早地显示自定义PopupWindow

虽然500毫秒的延迟可以缓解某些设备上的问题,但它不是解决方案。您会注意到,如果您将延迟设置为1000毫秒,那么问题很可能永远消失。这同样不是解决办法

为保证安全,采用以下方法:

让活动告诉您何时可以显示您的弹出窗口。在您的情况下,可以在找到微调器后立即进行设置:

下一步,向其发布Runnable:


此处无需延迟。

引发的异常表明您过早显示自定义PopupWindow

虽然500毫秒的延迟可以缓解某些设备上的问题,但它不是解决方案。您会注意到,如果您将延迟设置为1000毫秒,那么问题很可能永远消失。这同样不是解决办法

为保证安全,采用以下方法:

让活动告诉您何时可以显示您的弹出窗口。在您的情况下,可以在找到微调器后立即进行设置:

下一步,向其发布Runnable:

此处无需延迟。

首先:

mActivity
确保您没有保留活动引用。有更简单的方法,即获取片段的活动。如果片段被分离,它将自动返回null。当片段处于分离状态时,isAdded自动返回false。因此,停止持有额外的活动引用或片段状态变量,它们不会自动更新

然后:

当您计划一个runnable,它应该对UI做一些事情时,请记住android活动、片段或视图以及它的UI可以随时消失。所以,记住在UI消失时取消处理程序中的runnable。也就是说,在活动顶部,在片段的onDestroyView和自定义视图窗口的onDetachedFromWindow上

此外:

更好的检查方法是:

if (getActivity() != null && isAdded() && !getActivity().isFinishing() && mSpinner != null) {
  // do stuff
}
首先:

mActivity
确保您没有保留活动引用。有更简单的方法,即获取片段的活动。如果片段被分离,它将自动返回null。当片段处于分离状态时,isAdded自动返回false。因此,停止持有额外的活动引用或片段状态变量,它们不会自动更新

然后:

当您计划一个runnable,它应该对UI做一些事情时,请记住android活动、片段或视图以及它的UI可以随时消失。所以,记住在UI消失时取消处理程序中的runnable。也就是说,在活动顶部,在片段的onDestroyView和自定义视图窗口的onDetachedFromWindow上

此外:

更好的检查方法是:

if (getActivity() != null && isAdded() && !getActivity().isFinishing() && mSpinner != null) {
  // do stuff
}

表示弹出窗口位于微调器或活动上方?弹出窗口位于微调器上方,您在创建视图时创建微调器,但我在显示用于项目的API版本之前已检查其是否为null?表示弹出窗口位于微调器或活动上方?弹出窗口位于微调器上方,您在创建视图时创建微调器,但我在创建视图前已检查其是否为null显示用于project?I alrea的API版本
dy放入此更改,但不是在活动中设置它,而是在调用mSpinner.post之前将其放入Resume并检查mSpinner是否为null。我已经放入此更改,但不是在活动中设置它,而是在调用mSpinner.post之前将其放入Resume并检查mSpinner是否为null