Unable to add window -- token null is not valid; is your activity running?错误及其修改方法

先将错误帖上来:

E/AndroidRuntime(19905): FATAL EXCEPTION: main
E/AndroidRuntime(19905): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
E/AndroidRuntime(19905):        at android.view.ViewRootImpl.setView(ViewRootImpl.java:670)
E/AndroidRuntime(19905):        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:248)
E/AndroidRuntime(19905):        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
E/AndroidRuntime(19905):        at com.android.camera.OnScreenHint.handleShow(OnScreenHint.java:178)
E/AndroidRuntime(19905):        at com.android.camera.OnScreenHint.access$000(OnScreenHint.java:41)
E/AndroidRuntime(19905):        at com.android.camera.OnScreenHint$1.run(OnScreenHint.java:197)
E/AndroidRuntime(19905):        at android.os.Handler.handleCallback(Handler.java:800)
E/AndroidRuntime(19905):        at android.os.Handler.dispatchMessage(Handler.java:100)
E/AndroidRuntime(19905):        at android.os.Looper.loop(Looper.java:194)
E/AndroidRuntime(19905):        at android.app.ActivityThread.main(ActivityThread.java:5407)
E/AndroidRuntime(19905):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(19905):        at java.lang.reflect.Method.invoke(Method.java:525)
E/AndroidRuntime(19905):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
E/AndroidRuntime(19905):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
E/AndroidRuntime(19905):        at dalvik.system.NativeStart.main(Native Method)

这个错误还是第一次碰到。onScreenHint 其实本质上是一个 popup 弹出框。那么这个弹出框是要依赖于一个父窗口或者父 View 的。

这个错误的根本原因是说父窗口还未创建完成的时候就调用了这个弹出框导致失败。

最后根据上述调用栈,顺滕摸瓜找到是在 ActivityBase.java 的 onResume() 函数中调用的。

源代码:

        if (updateStorageHintOnResume()) {
        	showIfNeeded();
        }

上述代码中 showIfNeed() 函数间接调用了 OnScreenHint.java 类的 handleShow() 函数

	private synchronized void handleShow() {
        if (mView != mNextView) {
            // remove the old view if necessary
            handleHide();
            mView = mNextView;
            final int gravity = mGravity;
            mParams.gravity = gravity;
            if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK)
                    == Gravity.FILL_HORIZONTAL) {
                mParams.horizontalWeight = 1.0f;
            }
            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK)
                    == Gravity.FILL_VERTICAL) {
                mParams.verticalWeight = 1.0f;
            }
            mParams.x = mX;
            mParams.y = mY;
            mParams.verticalMargin = mVerticalMargin;
            mParams.horizontalMargin = mHorizontalMargin;
            if (mView.getParent() != null) {
                mWM.removeView(mView);
            }
            mWM.addView(mView, mParams);//出问题的正是这一行
        }
    }

父View 没有创建好,咋办呢?这里有一个最简单的办法就是过一段时间再调这个函数,将函数 showIfNeed() 或者 此函数中的弹出框调用部分放到一个 Handler 中,并且通过延时来触发。

修改方法如下:

修改为:

        if (updateStorageHintOnResume()) {
            updateStorageSpace();
            mHandler.sendEmptyMessageDelayed(UPDATE_STORAGE_HINT, 200);
        }
Handler 中的代码:
    private final Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case UPDATE_STORAGE_HINT:
                        updateStorageHint();
                        return;
                    case CLEAR_SCREEN_DELAY: {
                        getWindow().clearFlags(
                                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                        break;
                    }
                    case EXIT: {
                        finish();
                        break;
                    }
                }
            }
    };

说明一下:上面的修改中将 showIfNeed() 函数一分为二,并且将间接调用 OnScreenHint.java handleShow() 的部分放到了一个 Handler 中来做,并且通过延时来触发。这样就不太可能出现秀弹出框的时候其父 View 还没有创建好的情况了。

网上有一篇类似的文章描述了popupWindow 中同样的错误,有需要可以参考:http://cb269267.iteye.com/blog/1787779


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值