【问题标题】:android.view.WindowManager$BadTokenException while showing PopOver显示 PopOver 时出现 android.view.WindowManager$BadTokenException
【发布时间】:2015-11-16 20:22:50
【问题描述】:

我添加了以下代码以在我的微调器视图上显示一个弹出框。该代码使用自定义 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.setView(ViewRootImpl.java:532) 2 在 android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:259) 3 在 android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69) 4 在 android.widget.PopupWindow.invokePopup(PopupWindow.java:1019) 5 在 android.widget.PopupWindow.showAtLocation(PopupWindow.java:850) 6 在 android.widget.PopupWindow.showAtLocation(PopupWindow.java:814) 7 在 com.PopOver.show(PopOver.java:339) 8 在 com.MainFragment.displayPopOver(MainFragment.java:515) 9 在 com.MainFragment.access $1300(MainFragment.java:73) 10 在 com.MainFragment$5.run(MainFragment.java:497) 11 在 android.os.Handler.handleCallback(Handler.java:733) 12 在 android.os.Handler.dispatchMessage(Handler.java:95) 13 在 android.os.Looper.loop(Looper.java:136) 14 在 android.app.ActivityThread.main(ActivityThread.java:5001) 15 在 java.lang.reflect.Method.invokeNative(Native Method) 16 在 java.lang.reflect.Method.invoke(Method.java:515) 17 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 18 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 19 在 dalvik.system.NativeStart.main(Native Method)

【问题讨论】:

  • 意味着弹出窗口结束于 Spinner 或 Activity?
  • 弹出窗口在微调器上
  • 你在哪里创建微调器
  • 在 onCreateView() 但我在显示 PopOver 之前检查了它是否为空
  • 项目使用哪个 API 版本?

标签: java android android-fragments android-activity android-popupwindow


【解决方案1】:

抛出的异常表明您即将显示自定义PopupWindow

虽然500 ms 延迟可能会缓解某些设备上的问题,但这不是解决方案。你会注意到,如果你延迟说1000 ms,问题很可能会永远消失。这又是不是的解决方案。

为保证,采用以下方法:

让活动告诉您何时准备好显示您的PopupWindow。在您的情况下,您可以在找到Spinner 后立即设置:

mSpinner = (Spinner) findViewById(R.id.spinner); 

接下来,给它发一个Runnable

mSpinner.post(new Runnable() {
    public void run() {
        displayPopOver();
    }
});

这里不需要延迟。

【讨论】:

  • 我已经进行了此更改,但我没有将其设置在活动中,而是将其放入 onResume 并在调用 mSpinner.post 之前检查 mSpinner 是否不为空
【解决方案2】:

首先:

mActivity

确保您没有坚持活动参考。有更简单的方法,即片段的getActivity()。如果您的片段已分离,它将自动返回null。当片段处于​​分离状态时,isAdded() 自动返回 false。因此,停止持有额外的 Activity 引用或片段状态变量,它们不会自动更新。

然后:

当您安排一个应该对 UI 执行某些操作的可运行对象时,请记住,android ActivityFragmentView 以及它的 UI 可以随时消失。因此,记住在 UI 消失时从处理程序中取消该可运行对象。也就是说,onStop() 的活动和onDestroyView() 的片段和onDetachedFromWindow() 的自定义视图。

还有:

更好的检查是:

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

【讨论】:

    猜你喜欢
    • 2016-11-26
    • 2017-11-28
    • 1970-01-01
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    相关资源
    最近更新 更多