Window和WindowManager的关系

在应用中,任何要显示的界面都要依附在Window上,比如Activity、Dialog、Toast都是在window中显示的。Window 是一个抽象类,表示一个窗口,它的具体实现类是 PhoneWindow。实现位于WindowManagerService 中,WindowManagerService位于Android系统架构的Framework层。

Window 分类

Window 有三种类型,分别是应用 Window、子 Window 和系统 Window。应用类 Window 对应一个 Acitivity,子 Window 不能单独存在,需要依附在特定的父 Window 中,比如常见的一些 Dialog 就是一个子 Window。系统 Window是需要声明权限才能创建的 Window,比如 Toast 和系统状态栏都是系统 Window。

Window添加子view

对 Window 的操作是通过 WindowManager 来完成的,WindowManager 是一个接口,它继承自只有三个方法的 ViewManager 接口,包括添加、删除、更新view:

public interface ViewManager{
    public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);
}

setContentView()在下层调用的就是windowManager的addview()方法。Window内部有叫decorview的根view,将setContentview()传入的view添加到decorvew中,就将view绑定到window中了。

  • setContentView的具体过程

首先去获取getWindow(),返回的是window调attch时创建PhoneWindow对象,调用其setContentView。

public void setContentView(@LayoutRes int layoutResID) {
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

PhoneWindow中的setContentView方法:

    @Override
    public void setContentView(int layoutResID) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }

首先mContentParent是一个ViewGroup,我们先对mContentParent进行判空处理,如果为空调用了installDecor()方法,如果mContentParent不为空,那么移除当前ViewGroup的所有子View。

mLayoutInflater在phoneWindow创建的时候被赋值。

  public PhoneWindow(Context context) {
        super(context);
        mLayoutInflater = LayoutInflater.from(context);
    }

再看PhoneWindow类中installDecor中部分代码:

private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
            mDecor = generateDecor(-1);
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        } else {
            mDecor.setWindow(this);
        }

      ...
}

mDecor为空则创建一个DecorView,不为空则将当前自己设置给DecorView中的PhoneWindow对象,将inflater引入的view添加到decorView中。

你可能感兴趣的:(Window和WindowManager的关系)