Android中Window,DecorView和ViewRoot

1.Window

Window是一个抽象类,具体实现是PhoneWindow. Android中所有的视图都是通过Window来呈现的.
每一个Window都对应着一个View和一个ViewRootImpl,Window和View是通过ViewRootImpl来建立联系,Window并不是实际存在的,View才是Window存在的实体.(View不能单独存在,必须依附在Window上)

1.1 Window和WindowManager

WindowManager是外界访问Window的入口,创建一个Window也是通过WindowManager来实现的. WindowManager继承自ViewManager,常用的有三个功能:

  • 创建一个Window并向其添加View
  • 更新Window中的View
  • 删除一个View

1.2 Activity的Window创建过程

Activity的启动过程这里就不过多描述了,最终是由ActivityThread中的performLaunchActivity()来完成启动过程,并调用attach方法,在attach方法中最终会创建PhoneWindow

mWindow = new PhoneWindow(this, window, activityConfigCallback);

2.DecorView

DecorView是一个FrameLayout,是Activity中的顶级View,一般内部包含标题栏和内容栏,但是会随着主题而发生变化;内容栏是一定存在的,完整的id是android.R.id.content;在Activity中通过setContentView()设置的布局文件就是加载到了内容栏中.

2.1 setContentView源码分析

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

这里的getWindow()获取的就是在attach方法中创建的PhoneWindow实例,所以我们看一下PhoneWindowsetContentView()方法

 public void setContentView(int layoutResID) {
        // 如果mContentParent为空,就去创建一个DecorView
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        //如果不为空,就删除其中的View
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
        //把布局文件添加到mContentParent中
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
        //回调通知,内容发生改变了
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }

这里的mContentParent实际上就是前面提到的id为contentFrameLayout,这个通过源码可以看出来. 接着看一下 installDecor()

    private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
            mDecor = generateDecor(-1);//创建DecorView
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        } else {
            mDecor.setWindow(this);
        }
        if (mContentParent == null) {
        //为DecorView设置布局格式,并返回id为content的FrameLayout
            mContentParent = generateLayout(mDecor);
            ......
    }

看一下 generateDecor()

    protected DecorView generateDecor(int featureId) {
        ......
        return new DecorView(context, featureId, this, getAttributes());
    }

就是简单的创建了一个DecorView

generateLayout()主要就是先获取主题的样式,然后根据样式加载对应的布局到DecorView中,然后再获取mContentParent并返回,就可以把布局文件添加到mContentParent中了,即Activity所需要展示的布局.
到这为止,Activity的布局文件已经成功添加到了DecorViewmContentParent中,但是DecorView还没有被WindowManager添加到Window中,即用户还不能看到视图.

2.2 DecorView的展示

这里不过多描述Activity的启动过程,在ActivityThreadhandleResumeActivity方法中,首先会调用Activity的onResume方法,接着会调用Activity的makeVisible()

    void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

到此DecorView真正完成了添加和显示这两个过程,视图就可见了.

我们来看一下addView()这个方法,WindowManager是个接口,具体实现类是由WindowManagerImpl来实现的

      public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        ......
        ViewRootImpl root;
        root = new ViewRootImpl(view.getContext(), display);
        view.setLayoutParams(wparams);

        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);
       ......
       try {
       	  //将DecorView交给ViewRootImpl
          root.setView(view, wparams, panelParentView);
       } catch (RuntimeException e) {
        }
    }

这里实例化了ViewRootImpl对象,然后调用setView()方法,setView()经过一系列的处理最终会调用performTraversals()方法,开始进行View的measure,layout,draw流程,把界面显示出来.

3. ViewRoot

ViewRoot对应于ViewRootImpl类,是连接WindowManagerDecorView的纽带,View的三大流程均是通过ViewRoot来完成的. 在ActivityThread中,Activity对象创建成功后,会将DecorView添加到Window中,同时会创建ViewRootImpl对象,并将ViewRootImpl对象和DecorView建立关联.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值