通过测量确定了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开始绘制,前面所做的一切工作都是准备工作,而现在则是正式开始绘制流程。和之前的逻辑差不多,这里,回来用到在做分析