通过测量确定了View成员变量mMeasuredWidth和mMeasuredHeight的值,通过布局确定了View相对于父View左上右下的值。当所有的View的大小和位置全部确定之后,我们就可以进行绘制了。
三大工作流程始于ViewRootImpl#performTraversals,在这个方法内部会分别调用performMeasure,performLayout,performDraw三个方法来分别完成测量,布局,绘制流程。那么我们现在先从performDraw方法看起,ViewRootImpl#performDraw
private void performDraw() {
try {
draw(fullRedrawNeeded);
} finally {
mIsDrawing = false;
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}上边方法调用ViewRootImpl中的drow方法,注意这里调用的是自己类中的draw方法。并传递了fullRedrawNeeded参数,而该参数由mFullRedrawNeeded成员变量获取,它的作用是判断是否需要重新绘制全部视图,如果是第一次绘制视图,那么显然应该绘制所以的视图,如果由于某些原因,导致了视图重绘,那么就没有必要绘制所有视图。继续看draw方法
private void draw(boolean fullRedrawNeeded) {
//获取mDirty,该值表示需要重绘的区域
final Rect dirty = mDirty;
if (mSurfaceHolder != null) {
// The app owns the surface, we won't draw.
dirty.setEmpty();
if (animating) {
if (mScroller != null) {
mScroller.abortAnimation();
}
disposeResizeBuffer();
}
return;
}
//第一次绘制流程,设置需要绘制所有视图
if (fullRedrawNeeded) {
mAttachInfo.mIgnoreDirtyState = true;
dirty.set(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
}
//然后把绘制区域和相关参数传递过去
if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
return;
}
}我们继续看drawSofeware方法
private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
boolean scalingRequired, Rect dirty) {
//锁定canvas区域,由dirty区域决定
canvas = mSurface.lockCanvas(dirty);
//正式开始绘制,这里的mView是DecorView
mView.draw(canvas);
}mView就是DecorView,也就是说从DecorView开始绘制,前面所做的一切工作都是准备工作,而现在则是正式开始绘制流程。和之前的逻辑差不多,这里分析的很好,回来用到在做分析