Android中Window添加View的底层原理

2019-12-10 18:54:25刘景俊

在WindowManagerService内部会为每一个应用保留一个单独的session。
2.window的删除
看下WindowManagerGlobal的removeView:

public void removeView(View view, boolean immediate) { 
    if (view == null) { 
      throw new IllegalArgumentException("view must not be null"); 
    } 
 
    synchronized (mLock) { 
      int index = findViewLocked(view, true); 
      View curView = mRoots.get(index).getView(); 
      removeViewLocked(index, immediate); 
      if (curView == view) { 
        return; 
      } 
 
      throw new IllegalStateException("Calling with view " + view 
          + " but the ViewAncestor is attached to " + curView); 
    } 
  } 

首先调用findViewLocked来查找删除view的索引,这个过程就是建立数组遍历。然后再调用removeViewLocked来做进一步的删除。

private void removeViewLocked(int index, boolean immediate) { 
    ViewRootImpl root = mRoots.get(index); 
    View view = root.getView(); 
 
    if (view != null) { 
      InputMethodManager imm = InputMethodManager.getInstance(); 
      if (imm != null) { 
        imm.windowDismissed(mViews.get(index).getWindowToken()); 
      } 
    } 
    boolean deferred = root.die(immediate); 
    if (view != null) { 
      view.assignParent(null); 
      if (deferred) { 
        mDyingViews.add(view); 
      } 
    } 
  } 

真正删除操作是viewRootImpl来完成的。windowManager提供了两种删除接口,removeViewImmediate,removeView。它们分别表示异步删除和同步删除。具体的删除操作由ViewRootImpl的die来完成。

boolean die(boolean immediate) { 
    // Make sure we do execute immediately if we are in the middle of a traversal or the damage 
    // done by dispatchDetachedFromWindow will cause havoc on return. 
    if (immediate && !mIsInTraversal) { 
      doDie(); 
      return false; 
    } 
 
    if (!mIsDrawing) { 
      destroyHardwareRenderer(); 
    } else { 
      Log.e(TAG, "Attempting to destroy the window while drawing!n" + 
          " window=" + this + ",    } 
    mHandler.sendEmptyMessage(MSG_DIE); 
    return true; 
  }