Bootstrap

Android的View体系(二):DecorView的创建与显示

DecorView是顶级View,一般情况下它内部会包含一个竖直方向的LinearLayout,在这个LinearLayout里面有上下2部分,上面是标题栏,下面是内容栏。在Activity中我们通过setContentView所设置的布局文件其实就是被加载到内容栏之中。

本文,将介绍DecorView是如何创建与显示的。

说明:本文若无特殊说明,源码分析对应为api21。

一.DecorView的创建

上面我们提到,DecorView是显示的顶层View,那么View的绘制准备从DecorView开始说起。而DecorView的开始 就是我们熟悉的 setContentView()。

   //代码片1 (Activity类)
   public void setContentView(int layoutResID) {
   
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

查看后发现,getWindow()返回的是Window类。而我们知道,Window是抽象类,而PhoneWindow是它的唯一实现类。也就是说,想了解 getWindow().setContentView(layoutResID) ,其实是PhoneWindow类的setContentView 方法。

//代码片2(PhoneWindow类)
@Override
    public void setContentView(int layoutResID) {
   
        // 1. 若mContentParent为空,创建一个DecroView
  		// mContentParent即为内容栏(content)对应的DecorView = FrameLayout子类
        if (mContentParent == null) {
   
            installDecor();      ---->分析1
        } 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 {
   
            // 2. 为mContentParent添加子View
           // 即Activity中设置的布局文件
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
   
            cb.onContentChanged();
        }
    }

我们来看一下代码片2中的分析1部分(即第7行代码):

//代码片3(PhoneWindow类)
 private void installDecor() {
   
        if (mDecor == null) {
   
            //1. 通过赋值可以发现,mDecor就是DecorView。
            //  (DecorView的描述)This is the top-level view of the window, containing the window decor. 
            //  private DecorView mDecor;
  
;