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

你可能感兴趣的:(WindowManager addView异常)