Android UI的绘制显示流程
- Activity 加载和解析布局文件,根据配置文件生成相应的View 对象实例
- 在Activity 的PhonewWindow 中创建DecorView,解析布局文件生成View Tree
- 在Activity 对应的WMS实例中创建ViewRoot,View的三大流程 测量,布局,绘制均通过ViewRoot来完成
- ViewRoot 需要和 Choreographer 交互,当任意View 发生变化的时候,首先执行到ViewRoot 的 Layout 和 measure,然后请求Vsync,在Vsync 到来之后,回调View 中的 input,animation,draw 等事件
- 在View 的 draw 函数中,将绘制指令以Displaylist 的格式记录下来,统一送到RenderThread 去渲染
- RenderThread 中会通过BufferQueue 申请 Buffer,使用GPU 接口渲染Buffer,渲染完成后,触发SurfaceFlinger 完成更新操作
![](https://img.haomeiwen.com/i16401219/dd32f2412b70d8c6.jpg)
DecorView简介
DecorView是FrameLayout的子类,是Android视图树的根节点视图,DecorView作为Top View,一般情况下它内部包含一个竖直方向的LinearLayout,这个LinearLayout包含两个部分,由上到下分别是:
- ActionBar(ViewStub) TileView (标题栏)
-
Content View(内部视图)
我们在APK里定义的View 布局对应的就是ContentView的布局,如下图所示:
DecorView.jpg
ViewRoot 简介
ViewRoot对应ViewRootImpl类,它是连接WindowManagerService和DecorView的纽带,View的三大流程(测量(measure),布局(layout),绘制(draw))均通过ViewRoot来完成;
ViewRoot 本质上并不是一个View,并不是View 的子类和父类,但是它实现了ViewParent接口,这让它可以作为View的名义上的父视图;RootView继承了Handler类,可以接收事件并分发,Android的所有触屏事件、按键事件、界面刷新等事件都是通过ViewRoot进行分发的,下图可以表面ViewRoot 和 View 之间的逻辑关系
![](https://img.haomeiwen.com/i16401219/6ea8a12360fc6f99.jpg)
DecorView 的创建流程
DecorView 的创建流程如下所示:
![](https://img.haomeiwen.com/i16401219/e88c43df65930b85.png)
重要代码位置:
/framework/base/core/java/android/view
/frameworks/base/core/java/android/app/
/frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
- Acitvity.java 中的 attach函数中创建了PhoneWindow,Acitvity的主要功能是控制生命周期,Window里的逻辑用于提供图形生成能力并且装饰
- setContentView 是用于设置ContentView的布局,这里会先调用**LayoutInflater **解析布局文件生成各个不同View的实例
ViewRootImpl 的创建流程
ViewRootImpl 的创建流程如下所示:
![](https://img.haomeiwen.com/i16401219/0b25b27d55cf3f14.jpg)
- ViewRootImpl 是一个非常关键的类,调用几次AddView 就会创建几个ViewRootImpl 的实例
- 由于WMG是单例的,所以该应用中创建的所有DecorView,ViewRootImpl 都会保存在 WindowMangerGlobal 中
- WindowMangerGlobal中重要函数dumpGfxInfo,包含了ViewTree 和 Displaylist的所有信息
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>();
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
synchronized (mLock) {
// Start watching for system property changes.
if (mSystemPropertyUpdater == null) {
mSystemPropertyUpdater = new Runnable() {
@Override public void run() {
synchronized (mLock) {
for (int i = mRoots.size() - 1; i >= 0; --i) {
mRoots.get(i).loadSystemProperties();
}
}
}
};
SystemProperties.addChangeCallback(mSystemPropertyUpdater);
}
int index = findViewLocked(view, false);
...... 省略
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
网友评论