Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android中View的绘制过程 #4

Open
zgq105 opened this issue Apr 16, 2019 · 0 comments
Open

Android中View的绘制过程 #4

zgq105 opened this issue Apr 16, 2019 · 0 comments

Comments

@zgq105
Copy link
Owner

zgq105 commented Apr 16, 2019

image

1. 什么是View,作用是什么?

Android中View直译为视图或则界面的意思,可以简单理解为APP中界面呈现出来的一个个元素就是View。它负责了Android中展示的部分。

2. View和ViewGroup区别

View是所有视图组件的基类,ViewGroup也是View的子类;在View中定义了展示组件的通用规则。ViewGroup是抽象类表示带有容器类性质的View,通常指Android中的布局组件,像RelativeLayout、FrameLayout、LinearLayout等都是继承ViewGroup。而一般非容器类的组件,像TextView,Button、ImageView等都是直接继承View实现的。所以,通俗点理解就是View代表非容器类视图组件,ViewGroup代表容器类视图组件。

3. Activity、Window和View关系

借用一张大神的图
image
在Android中,每个Activity都包含一个根窗口Window对象PhoneWindow;Window是一个抽象类,PhoneWindow继承Window,Activity中setContentView方法实际调用的就是PhoneWindow中的setContentView,如下图所示:

//Activity.java中setContentView
 public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

PhoneWindow里面包含了一个DecorView,它是FrameLayout,setContentView其实就是将layout资源设置到了这个容器类型的DecorView上。
**总结:**Activity包含PhoneWindow,PhoneWindow包含DecorView,DecorView包含ActionBar和我们自定义布局。

4. View的显示经历了哪些流程

4.1 xml转View过程(预处理阶段)

xml布局资源转View过程就是通过Activity中setContentView,本质是将xml文件通过布局填充机制转成View对象,然后再添加到DecorView中。可以理解Activity的setContentView方法是完成内容视图的创建与设置工作,接下来就是进入View的绘制流程。

4.2 测量阶段(measure)

在Activity的onCreate中完成了布局资源转成View并加入到DecorView中,在onResume中,就会完成整个View的绘制流程,首先建立DecorView和ViewRootImpl关联,ViewRootImpl是负责整个绘制的流程,具体关联过程如下:ActivityThread#handleResumeActivity->WindowManagerImpl#addView->WindowManagerGlobal#addView->ViewRootImpl#setView,到这个方法为止,DecorView就和ViewRootImpl关联上了。
image

接着上面的过程ViewRootImpl#setView -> ViewRootImpl#requestLayout -> ViewRootImpl#scheduleTraversals -> ViewRootImpl中内部类TraversalRunnable#doTraversal -> ViewRootImpl#performTraversals -> ViewRootImpl#measureHierarchy -> ViewRootImpl#performMeasure,在performMeasure中调用View类提供的measure方法进行测量工作,可以理解performMeasure方法是整个测量measure的入口,接着上面流程,ViewRootImpl#performMeasure
-> View#measure(中转方法) -> DecorView#onMeasure(实际测量工作),接下来就进入到View树的测量流程,如果是ViewGroup就计算自身的大小和递归循环计算子元素的大小,如果是普通的View就计算自身大小即可。
image
测量三种模式:

  1. MeasureSpec.UNSPECIFIED表示不限制大小模式。
  2. MeasureSpec.EXACTLY表示明确的指定大小模式,比如match_parent或则设置固定dp或px值。
  3. MeasureSpec.AT_MOST表示不超过固定大小模式,比如wrap_content。

注:一般自定义View需要重写onMeasure方法,实现自己的测量规则。

4.3 布局阶段(layout)

ViewRootImpl#performTraversals ->ViewRootImpl#performLayout -> DockView#layout(实际调用的父类View的方法) -> DockView#onLayout(实际布局工作),接下来就进入到View树的布局流程,如果是ViewGroup就计算自身的大小和递归循环布局子元素,如果是普通的View控制好自身布局即可。所谓布局就是如何将View摆放在某个位置的问题。

4.4 绘制阶段(draw)

ViewRootImpl#performTraversals -> ViewRootImpl#performDraw -> ViewRootImpl#draw -> ViewRootImpl#drawSoftware -> View#draw,在View的draw中完成所有绘制工作。主要绘制内容如下:

  1. 绘制背景。
  2. 绘制内容。
  3. 绘制子元素。
  4. 绘制装饰。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant