WindowManager addView异常

Google在8.0对WindowManagerGlobal修改,会使第一次addview因为BadTokenException or InvalidDisplayException的View没法被移除掉。index取值的地方在WindowManagerGlobal的addview方法中:

      int index = findViewLocked(view, false);
        if (index >= 0) {
            if (mDyingViews.contains(view)) {
                // Don't wait for MSG_DIE to make it's way through root's queue.
                mRoots.get(index).doDie();
            } else {
                throw new IllegalStateException("View " + view
                        + " has already been added to the window manager.");
            }
            // The previous removeView() had not completed executing. Now it has.
        }

        // If this is a panel window, then find the window it is being
        // attached to for future reference.
        if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
                wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
            final int count = mViews.size();
            for (int i = 0; i < count; i++) {
                if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
                    panelParentView = mViews.get(i);
                }
            }
        }

        root = new ViewRootImpl(view.getContext(), display);

        view.setLayoutParams(wparams);

        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);
    }

    // do this last because it fires off messages to start doing things
    try {
        root.setView(view, wparams, panelParentView);
    } catch (RuntimeException e) {
        // BadTokenException or InvalidDisplayException, clean up
         'synchronized (mLock) {
            final int index = findViewLocked(view, false);
            if (index >= 0) {
                removeViewLocked(index, true);
            }
        }'
    
        throw e;
}

在8.0之后

 synchronized (mLock) {
        final int index = findViewLocked(view, false);
        if (index >= 0) {
            removeViewLocked(index, true);
        }
 }

变成了

       if (index >= 0) {
            removeViewLocked(index, true);
        }

但是这里的Index会一直为-1。

下次再add同一View时,会因为上次没有执行removeViewLocked(int, boolean),抛出“has already been added to the window manager”。

解决方法:在addView(view)的地方catch异常,并手动执行removeView(view);

附google提交记录
image
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容