Android必读之View层级到底是什么样的

了解清楚Android View的层级关系有助于我们理解Android事件传递和优化App性能。
那么Android的View到底是如何一层层加载展示的呢?请先看下图:
《Android必读之View层级到底是什么样的》
上图布局代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ACTION 1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    //。。。。
</LinearLayout>

根布局

根据上图所示,DecorView为根布局,内部包含了三个View,分别是:LinearLayout、navigationBarBackgroud、statusBarBackground,根据App的theme和手机系统Level各这三个View略有有不同。我这是基于Android9.0,Theme为Theme.AppCompat.Light.DarkActionBar。
LinearLayout即为我们可以自由控制的区域。顾名思义navigationBarBackgroud、statusBarBackground分别为底部导航栏和顶部状态栏。

可控制区域

LinearLayout中包含action_model_bar_stub和FrameLayout.

  1. FrameLayout就是调用setContentView设置的View
  2. action_model_bar_stub 预留View,如需了解,点这里聊聊《ActionModel》

FrameLayout

可以看到FrameLayout子view并不是我们自定的XML,而是PhoneWindow为DecorView生成一个父View-decor_content_parent,这个View是干什么的呢,我们可以从源码中了解一二。

//Activity.java中
public void setContentView(View view, ViewGroup.LayoutParams params) {
        getWindow().setContentView(view, params);
        initWindowDecorActionBar();
}
//PhoneWindow.java中
@Override
    public void setContentView(int layoutResID) {
        if (mContentParent == null) {//mContentParent就是decor_content_parent
            installDecor();//初始化安装decorview
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            //。。。。
        }
        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            //。。。。
        } else {
            //设置我们的xml layout
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        //。。。。
    }
  1. Activity调用getWindow的setContentView
  2. PhoneWindow中判断ContentParent是否为null
  3. 初始化decoreview,继续看代码
       private void installDecor() {
            mForceDecorInstall = false;
            if (mDecor == null) {
                mDecor = generateDecor(-1);//生成decorview
                //。。。
            } else {
                mDecor.setWindow(this);
            }
          if (mContentParent == null) {
                mContentParent = generateLayout(mDecor);
           }
      //...
      }
  4. 继续看generateLayout
    protected ViewGroup generateLayout(DecorView decor) {
        //从这个方法中就可以看到contentParent的作用就是控制Activity的Title,ActionBar等属性
        TypedArray a = getWindowStyle();
        if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
            requestFeature(FEATURE_NO_TITLE);
        } else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) {
            // Don't allow an action bar if there is no title.
            requestFeature(FEATURE_ACTION_BAR);
        }
        //还有很多就不一一列举了
    } 

     

decor_content_parent内部即是xml定义的layout。
Android View的层级架构就简略的讲到这里了

点赞

发表评论