概述:
之前分析过一个activity的启动到显示流程,具体显示流程中分析过测量与布局流程,这里对具体的绘制渲染流程进行具体的分析。绘制的起始还是从ViewRootImpl开始,在进入到view之后会根据根据是否有边缘效果稍作区分主要包括以下几点:
- 绘制背景
- 如果存在边缘效果的话,保存画布图层用于给边缘效果做准备
- 调用ondraw实现具体的绘制流程
- 绘制子view
- 如果存在边缘效果的话,绘制边缘效果,恢复画布图层
- 绘制装饰(滚动条,前景色之类)
大体流程如下图:
其实从这个大体流程里也可以知道为什么自定义view的时候,如果是继承自view,那就必须要自己实现ondraw,因为从这里流程里,在view中并没有具体的绘制操作,只是绘制了前景、背景、边缘效果,具体的绘制在ondraw中,ondraw需要子类自己去实现。
ViewRootImpl中主要流程代码如下:
private void performDraw() {
......
try {
//这里传入的是true
draw(fullRedrawNeeded);
} finally {
mIsDrawing = false;
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
......
//这里是true
if (mReportNextDraw) {
mReportNextDraw = false;
......
try {
//向窗口管理服务发送界面绘制完成的消息
mWindowSession.finishDrawing(mWindow);
} catch (RemoteException e) {
}
}
}
draw方法较长,这里主要关注其进入drawSoftware的流程:
private void draw(boolean fullRedrawNeeded) {
......
if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
......
//这里采用硬件渲染来绘制,会重新走一遍performTraversals流程
mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
} else {
//如果硬件渲染器不为空,且不可用,则使能它,然后重新绘制之后返回
if (mAttachInfo.mHardwareRenderer != null &&
!mAttachInfo.mHardwareRenderer.isEnabled() &&
mAttachInfo.mHardwareRenderer.isRequested()) {
try {
mAttachInfo.mHardwareRenderer.initializeIfNeeded(
mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets);
} catch (OutOfResourcesException e) {
handleOutOfResourcesException(e);
return;
}
mFullRedrawNeeded = true;
scheduleTraversals();
return;
}
//否则调用软件绘制
if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
return;
}
}
}
......
}
private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
boolean scalingRequir