View的工作原理_初识ViewRoot和DecorView

初识ViewRoot和DecorView

ViewRoot:
ViewRoot对应ViewRootImpl类,它是连接windowManager和DecorView的纽带,是个连接器,负责WindowManagerService与DecorView之间的通信,View的三大流程(测量(measure),布局(layout),绘制(draw))均通过ViewRoot来完成。

ViewRoot并不属于View树的一份子。从源码实现上来看,它既非View的子类,也非View的父类,但它实现了ViewParent接口,这让它可以作为View的名义上的父视图。Android的所有触屏事件、按键事件、界面刷新等事件都是通过ViewRoot进行分发的。
下面我们看一下ViewRootImpl的产生过程

源码WindowManagerImpl

public final class WindowManagerImpl implements WindowManager {    
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    ...
    @Override
    public void addView(View view, ViewGroup.LayoutParams params) {
        mGlobal.addView(view, params, mDisplay, mParentWindow);
    }
}

源码WindowManagerGlobal#addView

public void addView(View view, ViewGroup.LayoutParams params,
     Display display, Window parentWindow) {

     final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
      ......
         synchronized (mLock) {

          ViewRootImpl root;
           //实例化一个ViewRootImpl对象
          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()方法(performTraversals:执行遍历),然后依照下图流程层层调用,完成绘制,最终界面才显示出来。
在这里插入图片描述
其中:measure用来测量view的宽高,Layout用来确定View在父容器中放置的位置,即view4个顶点的坐标和实际View的宽高,draw负责把View绘制在屏幕上,

performTraversals的大致流程是这样的:

performTraversals会依次调用performMeasure,performLayout,performDraw三个方法,这3个方法分别完成顶级ViewGroup的
Measure,Layout,Draw. 这3大流程,其中performMeasure会调用Measure方法来测量自己,因为是ViewGroup,除了测量自己外,还要测量子孩子,所以在Measure方法中会调用onMeasure方法,在onMeasure方法中会对所有的子孩子进行Measure过程,这个时候Measure过程就从父容器传到子元素啦,这样就完成了一次Measure过程,接着子元素就重复父元素的过程,如此反复就完成了整个View树的遍历,同理performLayout和performDraw的传递流程和performMeasure类似,唯一不同的是,performDraw的传递过程是在draw方法中通过dispatchDraw来实现的(而不是onDraw())

DecorView:
DecorView作为顶级View,它是继承于 frameLayout,它内部会包含一个熟直方向的Linarlayout,Linarlayout里有上下两部分(具体情况和android版本和主题有关),上面是标题栏,下面是内容栏…在activity中,我们通过setContentView所设置的布局其实就是被加载在内容栏上,setContentView所对应的View 可以通过这种方式得到findViewByID(android.R.id.content).getChildAt(0)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值