11月更文挑战|Android基础-View基础DecorView浅析

289 阅读2分钟

这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战

View加载流程

View的绘制流程是在ViewRoot的performTraversals方法开始,然后再经过measure、layout和draw三个方法后最终将View绘制展示在页面中。在此过程当中measure方法回调是在测量View的宽和高;layout方法回调是来确定View在其父视图坐标位置;draw方法回调就是来绘制View。

performTraversals的执行过程中会依次调用preformMeasure、performLayout、performDraw方法。在这三个方法执行过程中又会分别先调用整个View树中顶级View的measure、layout和draw方法。其中当执行到视图是ViewGroup时依次调用方法onMeasure、onLayout和onDraw去执行它所有子视图中所对应的onMeasure、onLayout和onDraw方法,整个方法执行是从父级向子级去传递执行。

PhoneWindow

PhoneWindow是继承于Window类并是它的具体实现,可以通过PhoneWindow去绘制窗口。另外PhoneWindow内部包含DecorView作为应用窗口的根View。可以理解为PhoneWindowFrameLayout视图进行一定程度封装后作为根视图提供出一系列窗口操作方法。

ViewRootImpl

ViewRootImplView中最高层级是所有View的根,但ViewRootImpl并不是View,只是实现ViewParent接口作为ViewWindowManager之间的通信协议。

ViewRoot

ViewRoot对应ViewRootImpl类,作为WindowManagerDecorView连接桥梁。View的三大流程(测量(measure),布局(layout),绘制(draw))都是通过ViewRoot来完成,同时负责将DecorView添加到Window中,创建ViewRootImpl对象和DecorView建立联系。另外ViewRoot还负责Android中的触摸事件、按键事件、界面刷新等事件分发。

DecorView

DecorViewActivity窗口的顶级View且它是FrameLayout视图,通常情况下内部默认包含一个子视图LinearLayout,里面默认包含了上方标题栏(ActionBar),下面内容窗口(ContentParent)也就是开发在setContentView()去创建的页面信息。

Activity来看,每个Activity都对应一个窗口PhoneWindow。而PhoneWindow对应布局就是DecorView。所以不能认为开发者调用setContentView()方法创建的页面内容是最上层的视图了,它只是DecorView视图下ContentParent子视图的内容而已。

从Activity源码角度上看可以发现,上层setContentView()方法创建内容确实是add在是ViewGroup类型叫做contentParent视图上。

@Override
public void setContentView(View v) {
    ensureSubDecor();
    ViewGroup contentParent = mSubDecor.findViewById(android.R.id.content);
    contentParent.removeAllViews();
    contentParent.addView(v);
    mAppCompatWindowCallback.getWrapped().onContentChanged();
}

整体框架图

image.png

参考