View的介绍
Android View 有各种各样的布局(LinearLayout,FrameLayout,TableLayout,Relativelayout,AbsoluteLayout);View 绘制的三大步骤(Meaure,Layout,Draw)
注意View 绘制的三大步骤都是在Choreographer 的协调下进行的,这个下一章会讲
一些重要概念:
- Activity:应用程序的基本组件,提供一个屏幕,为用户完成某些交互的任务
- View:所有图形的基类
- ViewGroup:是View的子类,本身是一个View,但是也作为View 的容器
- Window/PhoneWindow:Window 概括了android 窗体的基本属性和功能,phoneWindow 是Window的子类
- DecorView:界面的 RootView,PhoneWindow 的内部类
- ViewRootImpl :是 ViewSystem 和 SurfaceSystem 的桥梁
View和ViewGroup 之间的关系如下:
WindowManagerGlobal
ViewRootImpl 是在 WindowManagerGlobal 中被创建的
WindowManagerImpl 是 WindowManager 的实现类,WindowManagerImpl 内部方法实现都是代理类WindowManagerGlobal 完成的;
WindowManagerGlobal 使用的是单例模式,也就是一个进程中只有一个 WindowManagerGlobal 对象服务所有页面的View
特别注意:WindowManagerGlobal 内部中存储着 ViewRootImpl 和 View 的映射关系
public final class WindowManagerGlobal {
private final ArrayList<View> mViews = new ArrayList<View>();
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
private final ArrayList<WindowManager.LayoutParams> mParams =
new ArrayList<WindowManager.LayoutParams>();
private final ArraySet<View> mDyingViews = new ArraySet<View>();
}
所有创建的 ViewRootImpl 实例都会保存在mRoots这个ArrayList中;
所有添加View 都会保存在 mViews 的ArrayList 中,实际上添加的View 就是PhoneWindow中创建的 DecorView对象
ViewRootImpl
ViewRootImpl 是 ViewSystem 和 SurfaceSystem 的桥梁,PhoneWindow 中创建的 DecorView对象会通过 setView 的方式设置给它,因为View 的实现是 ViewTree的形式,所以根据DecorView遍历到所有的 View list
ViewRootImpl 内部会获取到 Choreographer 对象,根据 Choreographer 提供的节奏 调用 View 的三大方法
ViewRootImpl 的构成
ViewRootImpl 实现了 ViewParent 接口, ViewParent接口定义了 View 的基本操作
public interface ViewParent {
public void requestLayout();
public boolean isLayoutRequested();
public void invalidateChild(View child, Rect r);
.....
public ViewParent getParent();
public ViewParent invalidateChildInParent(int[] location, Rect r);
public void requestChildFocus(View child, View focused);
public void clearChildFocus(View child);
}
-
将DecorView 设置到 ViewRootImpl
上面的 ViewRootImpl创建流程中,注意最后一步的 setView 操作,其功能就是将 WindowManagerGlobal 中的 DecorView 设置到 ViewRootImpl 中
View 的 Measure
ViewRootImpl调用performMeasure执行Window对应的View的测量
ViewRootImpl的performMeasure 主要逻辑:
- DecorView(FrameLayout)的measure;
- DecorView(FrameLayout)的onMeasure;
- DecorView(FrameLayout)所有子View的measure;
View 的 Layout
ViewRootImpl调用performLayout执行Window对应的View的布局
ViewRootImpl的performLayout;
- DecorView(FrameLayout)的layout方法;
- DecorView(FrameLayout)的onLayout方法;
- DecorView(FrameLayout)的layoutChildren方法;
- DecorView(FrameLayout)的所有子View的Layout;
ViewRootImpl调用performDraw执行Window对应的View的布局
View 的 Draw
ViewRootImpl的performDraw,ViewRootImpl的draw,ViewRootImpl的drawSoftware;
DecorView(FrameLayout)的draw方法;
DecorView(FrameLayout)的dispatchDraw方法;
DecorView(FrameLayout)的drawChild方法;
DecorView(FrameLayout)的所有子View的draw方法;
View 视图的更新流程
用户点击屏幕产生了一个触摸行为,这个触摸行为是通过底层的硬件捕获,然后交给ViewRootImpl,接着将事件传递给DecorView,DecorView 交给 PhoneWindow,PhoneWindow再交给Activity
更新流程如下:
硬件 ViewRootImpl DecorView PhoneWindow Activity
由此可见ViewRootImpl的重要性,是个连接器,负责WindowManagerService与DecorView之间的通信
View 中的任何变化,最后都会汇总到 ViewRootImpl 的 scheduleTraversals函数,scheduleTraversals 会根据 Choreographer 提供的节奏,调用 performTraversals 完成 View 的三大操作 Measure,Layout,Draw