UI绘制流程之Draw绘制流程

本文详细解析了Android中UI的绘制流程,从ViewRootImpl的performDraw方法开始,介绍了包括初始化Canvas、绘制背景、保存图层、绘制内容、遍历子View等一系列步骤。通过源码分析,阐述了自定义View时如何参与绘制流程,并强调了Paint和Canvas在绘制过程中的重要性。文章结尾预告了后续将探讨的Paint和Canvas的相关内容。
摘要由CSDN通过智能技术生成

前言

从前面的几篇文章,我门能够的到知道ui的测量和布局,那么这次,我们首先来关注下我门的ui是怎么具体画出来的。那么在这里我们首先需要了解的是具体绘制的流程以及,paint和Canvas在这中间所扮演的角色

绘制流程

在之前的课程里我们都提到了在performTraversals当中一次调用了performMeasure,performLayout,performDraw那么前两者我们现在不关注, 现在主要关注draw正在具体干嘛,那么我们看到ViewRootImpl. performDraw方法看下他是如何完成具体绘制的在performTraversals中是这样

     // Remember if we must report the next draw.
    if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
   
        reportNextDraw();
    }

    boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;

    if (!cancelDraw && !newSurface) {
   
        if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
   
            for (int i = 0; i < mPendingTransitions.size(); ++i) {
   
                mPendingTransitions.get(i).startChangingAnimations();
            }
            mPendingTransitions.clear();
        }

        performDraw();
    } else {
   
        if (isViewVisible) {
   
            // Try again
            scheduleTraversals();
        } else if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
   
            for (int i = 0; i < mPendingTransitions.size(); ++i) {
   
                mPendingTransitions.get(i).endChangingAnimations();
            }
            mPendingTransitions.clear();
        }
    }

    mIsInTraversal = false;

在这里我们可以看到一个关键点就是在isViewVisible = true(也就是view为显示状态下,这里会在此发起一次scheduleTraversals,所以,这也是为什么我们的onMeasure会调用两次的原因)。接着进入performDraw我门具体来探寻他做了什么

    private void performDraw() {
   
    if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
   
        return;
    } else if (mView == null) {
   
        return;
    }

    final boolean fullRedrawNeeded = mFullRedrawNeeded;
    mFullRedrawNeeded = false;

    mIsDrawing = true;
    Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
    try {
   
        draw(fullRedrawNeeded);
    } finally {
   
        mIsDrawing = false;
        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
    }

    // For whatever reason we didn't create a HardwareRenderer, end any
    // hardware animations that are now dangling
    if (mAttachInfo.mPendingAnimatingRenderNodes != null) {
   
        final int count = mAttachInfo.mPendingAnimatingRenderNodes.size();
        for (int i = 0; i < count; i++) {
   
            mAttachInfo.mPendingAnimatingRenderNodes.get(i).endAllAnimators();
        }
        mAttachInfo.mPendingAnimatingRenderNodes.clear();
    }

    if (mReportNextDraw) {
   
        mReportNextDraw = false;

        // if we're using multi-thread renderer, wait for the window frame draws
        if (mWindowDrawCountDown != null) {
   
            try {
   
                mWindowDrawCountDown.await();
            } catch (InterruptedException e) {
   
                Log.e(mTag, "Window redraw count down interruped!");
            }
            mWindowDrawCountDown = null;
        }

        if (mAttachInfo.mThreadedRenderer != null) {
   
            mAttachInfo.mThreadedRenderer.fence();
            mAttachInfo.mThreadedRenderer.setStopped(mStopped);
        }

        if (LOCAL_LOGV) {
   
            Log.v(mTag, "FINISHED DRAWING: " + mWindowAttributes.getTitle());
        }

        if (mSurfaceHolder != null && mSurface.isValid()) {
   
            SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::postDrawFinished);
            SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();

            sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
        } else {
   
            pendingDrawFinished();
        }
    }
}

这里会看到调用了draw方法而该参数由mFullRedrawNeeded成员变量获取,它的作用是判断是否需要重新绘制全部视图,如果是第一次绘制视图,那么显然应该绘制所以的视图,如果由于某些原因,导致了视图重绘,那么就没有必要绘制所有视图

   private void draw(boolean fullRedrawNeeded) {
   
    Surface surface = mSurface;
    if (!surface.isValid()) {
   
        return;
    }

    if (DEBUG_FPS) {
   
        trackFPS();
    }

    if (!sFirstDrawComplete) {
   
        synchronized (sFirstDrawHandlers) {
   
            sFirstDrawComplete = true;
            final int count = sFirstDrawHandlers.size();
            for (int i = 0; i< count; i++) {
   
                mHandler.post(sFirstDrawHandlers.get(i));
            }
        }
    }

    scrollToRectOrFocus(null, false);

    if (mAttachInfo.mViewScrollChanged) {
   
        mAttachInfo.mViewScrollChanged = false;
        mAttachInfo.mTreeObserver.dispatchOnScrollChanged();
    }

    boolean animating = mScroller != null && mScroller.computeScrollOffset();
    final int curScrollY;
    if (animating) {
   
        curScrollY = mScroller.getCurrY();
    } else {
   
        curScrollY = mScrollY;
    }
    if (mCurScrollY != curScrollY) {
   
        mCurScrollY = curScrollY;
        fullRedrawNeeded = true;
        if (mView instanceof RootViewSurfaceTaker) {
   
            ((RootViewSurfaceTaker) mView).onRootViewScrollYChanged(mCurScrollY);
        }
    }

    final float appScale = mAttachInfo.mApplicationScale;
    final boolean scalingRequired = mAttachInfo.mScalingRequired;

    int resizeAlpha = 0;
    //获取mDirty,该值表示需要重绘的区域,就是之前我们最先做的那个定位
    final Rect dirty = mDirty;
    if (mSurfaceHolder != null) {
   
        // The app owns the surface, we won't draw.
        dirty.setEmpty();
        if (animating && mScroller != null) {
   
            mScroller.abortAnimation();
        }
        return;
    }
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值