android源码之View绘制

view 绘制主要流程

  • measure 计算view的大小
  • layout 计算view的位置
  • draw 绘制view

1.Activity.java##setContentView()中会创建DecorView, 通过LayoutInflater将xml文件解析出来,构建LinearLayout整个view树
2.Activity.java##resume() 中会将view 添加到window中

view 绘制流程前因后果

view 绘制的流程主要发生在ViewRootImpl.java中
在3中情况下会调用ScheduleTraversal()

  1. requestLayout
  2. requestFocus
  3. invalidate
void setView(....){
    // 在添加到window之前先进行一次layout,确保在接收到其他输入事件之前重新layout
    requestLayout();
    mSession.addToDisplay(...)
}

// 非常有意思的一个函数
// 首先从名称说起Schedule,部署计划,确实如此
//  这里用到了Handler机制的里的同步屏障[同步屏障:调整Message优先级的一种机制,设置同步屏障后,消息机制在处理消息的时候,会优先处理异步消息]
//  这个函数主要做了一下几件事情
//  1. 设置同步屏障
//  2. 在Chorographer中消息会最终设置成异步消息
//  3. mTraversalRunnable 回调执行方法doTraversal(). View绘制的核心函数
void scheduleTraversals() {
    if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            // 1 设置同步屏障
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            // 2.设置异步消息
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }
}
    // 取消同步屏障, 执行performTraversals() view的绘制生命周期
    void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }

            performTraversals();

            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }

view绘制流程performTraversals

ViewRootImpl.java

// 先吐槽一下这个函数的代码是在太长了,说好的面向对象的呢
private void performTraversals(){
    // 忽略。。。
    Rect frame = mWinFrame;
    // 1 计算desiredWindowWidth以及desiredWindowHeight, 以及相应标志
    if (mFirst) {
        // 第一次请求测量,布局, 绘制流程 
        mFullRedrawNeeded = true;
        mLayoutRequested = true;
      
        // 如果窗口的类型是有状体栏的, 那么Activity的窗口宽度和高度就是除了状态栏
        //   lp.type == TYPE_STATUS_BAR_PANEL || lp.type == TYPE_INPUT_METHOD || lp.type == TYPE_VOLUME_OVERLAY;
        if (shouldUseDisplaySize(lp)) {
            Point size = new Point();
            mDisplay.getRealSize(size);
            desiredWindowWidth = size.x;
            desiredWindowHeight = size.y;
        } else {
            // 否则Activity的宽高是整个屏幕的宽高        
            desiredWindowWidth = mWinFrame.width();
            desiredWindowHeight = mWinFrame.height();
        }
        // ....忽略
    } else {
        // 如果不是第一次请求绘制流程外,宽高会在winFrame中保存, 即上一次的长度
        desiredWindowWidth = frame.width();
        desiredWindowHeight = frame.height();
        // 注意这里的mWidth和mHeight是每次wms服务计算出来的
        if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) {
            // 当宽或者高繁盛变化了,则将设置相应的标志
            // 重新绘制标志,layout请求的标志, window尺寸可能发生变化标志
            mFullRedrawNeeded = true;
            mLayoutRequested = true;
            windowSizeMayChange = true;
        }
    }    

    // 2. 判断屏幕是否发生变化
    boolean layoutRequested = mLayoutRequested && (!mStopped || mReportNextDraw);
    // 接上,比如当发生了主懂requestLayout,或者屏幕尺寸发生变化
    if (layoutRequested) {
        // 
        final Resources res = mView.getContext().getResources();
        if (mFirst) {
                // make sure touch mode code executes by setting cached value
                // to opposite of the added touch mode.
            mAttachInfo.mInTouchMode = !mAddedTouchMode;
            ensureTouchModeLocally(mAddedTouchMode);
        } else {
            // 这里mOverscanInsets,mContentInsets, mStableInsets
            // 低版本使用的是ContentInset, 6.0以后换成OverScanInset
            // 在全屏状态下的window,利用inset来布局屏幕内部
            if (!mPendingOverscanInsets.equals(mAttachInfo.mOverscanInsets)) {
                insetsChanged = true;
            }
            if (!mPendingContentInsets.equals(mAttachInfo.mContentInsets)) {
                insetsChanged = true;
            }
            if (!mPendingStableInsets.equals(mAttachInfo.mStableInsets)) {
                insetsChanged = true;
            }
            if (!mPendingDisplayCutout.equals(mAttachInfo.mDisplayCutout)) {
                insetsChanged = true;
            }
            if (!mPendingVisibleInsets.equals(mAttachInfo.mVisibleInsets)) {
                mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets);
            }
            if (!mPendingOutsets.equals(mAttachInfo.mOutsets)) {
                insetsChanged = true;
            }
            if (mPendingAlwaysConsumeNavBar != mAttachInfo.mAlwaysConsumeNavBar) {
                    insetsChanged = true;
            }
            
            // 如果Activity的layoutparam被设置成AT_MOST模式时,
            // 意思是Activity窗口的大小要等于内容区域的大小, //但是Activity的大小要覆盖屏幕,所以Activity的宽高设置成当前屏幕的宽高
            // 这也意味着屏Activity窗口发生变化
            if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
                    || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                windowSizeMayChange = true;
                if (shouldUseDisplaySize(lp)) {
                    Point size = new Point();
                    mDisplay.getRealSize(size);
                    desiredWindowWidth = size.x;
                        desiredWindowHeight = size.y;
                } else {
                    Configuration config = res.getConfiguration();
                    desiredWindowWidth = dipToPx(config.screenWidthDp);
                    desiredWindowHeight = dipToPx(config.screenHeightDp);
                }
            }
        }

        // 3. 按照view的tree结构进行递归测量
        windowSizeMayChange |= measureHierarchy(host, lp, res,
                desiredWindowWidth, desiredWindowHeight);
        
        // 4。 layout
        if (didLayout) {
            performLayout(lp, mWidth, mHeight);
        }        
        // 5. 调用relayoutWindow 通过请求WMS来计算Activity穿欧的大小以及扫边区域inset大小,并且保存在mWinFrame中
        relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
        
        // 没有取消绘制以及没有新创建的surface
        if (!cancelDraw && !newSurface) {
            if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
                for (int i = 0; i < mPendingTransitions.size(); ++i) {
                    mPendingTransitions.get(i).startChangingAnimations();
                }
                mPendingTransitions.clear();
            }

            // 6. 执行draw操作
            performDraw();
        } else {
            if (isViewVisible) {
                // 重新来计算
                scheduleTraversals();
            } else if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
                for (int i = 0; i < mPendingTransitions.size(); ++i) {
                    mPendingTransitions.get(i).endChangingAnimations();
                }
                mPendingTransitions.clear();
            }
        }
    }       
}
view Measure 测量流程

private void measureHierarchy(){
    boolean goodMeasure = false;
    //。。。正常情况下不会发生
    if(!goodMeasure){
        childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);
        childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
        // 执行测量
        // MATCH_PARENT --> exactly
        // WRAP_CONTENT --> at_most
        
        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
    }
}

privoid void performMeasure(){
    // 注意这里实际调用到是View.java#measure方法
    DecorView.measure(childWSpec, childHSpec);
}
```

View.java 
```
public findal void measure(int wSpec, int hSpec){
    // layout 模式, LAYOUT_MODE_CLIP_BOUNDS,LAYOUT_MODE_OPTICAL_BOUNDS, 
    // 默认是LAYOUT_MODE_OPTICAL_BOUNDS,所以一般这个地方为false
    boolean optical = isLayoutModeOptical(this);
    
    if (optical != isLayoutModeOptical(mParent)) {
        // 如果当前的View的layoutMode与父mode不一致的情况下, 如果是option, 则减去insets, 否则+option
        Insets insets = getOpticalInsets();
        int oWidth  = insets.left + insets.right;
        int oHeight = insets.top  + insets.bottom;
        widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
        heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
    }

    // 压缩成一个long, 高32 + 低32
    long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
    if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);

    // 在被调用了requestlayou时会设置forceLayout
    final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;


    // 优化,对于exactl参数
    final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
                || heightMeasureSpec != mOldHeightMeasureSpec;
    final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
    final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
    final boolean needsLayout = specChanged
                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);

    if (forceLayout || needsLayout) {
        // 清除
        mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
        resolveRtlPropertiesIfNeeded();

        int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
        if (cacheIndex < 0 || sIgnoreMeasureCache) {
            // 当cache里面没有缓存数的时候,以当前的值继续计算
            onMeasure(widthMeasureSpec, heightMeasureSpec);
            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
        } else {
            // 有缓存的时候直利用缓存,避免每次都要调用onmeasure方法
            long value = mMeasureCache.valueAt(cacheIndex);
            // Casting a long to int drops the high 32 bits, no mask needed
            setMeasuredDimensionRaw((int) (value >> 32), (int) value);
            mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
        }

        // flag not set, setMeasuredDimension() was not invoked, we raise
        // an exception to warn the developer
        if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
                throw new IllegalStateException("View with id " + getId() + ": "
                        + getClass().getName() + "#onMeasure() did not set the"
                        + " measured dimension by calling"
                        + " setMeasuredDimension()");
        }

        mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
    }

    mOldWidthMeasureSpec = widthMeasureSpec;
    mOldHeightMeasureSpec = heightMeasureSpec;

    // 缓存保存上一次数据, 这里的缓存会在requestlayout的时候缓存清除
    mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
            (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension 
}

protect coid onMeasure(...){
    // 保存测量的w和h到mMeasuredWidth,mMeasureHeight
    setMeasureDimension(getDefaultSize(......), getDefualtSize(.....))
}
```

ViewGroup.java

```
protect void 

protected void measureChildren(in wSpec, int hSpec){
    
}

protect void measureChild(int wSpec, int hSpec){
    
}

protect void measureChildWithMargins(View child, ....){
    final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
    // 根据父view的限定以及自身的限定计算宽高
    // getChildMeasureSpec 是一个static方法
    final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
                        + widthUsed, lp.width);
    final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
                mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin
                        + heightUsed, lp.height);
                        
    child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}

 public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
     // 1. 分离父view的mode, size
     // 2. 计算当前父view的剩余空间size-padding
     // 3. 结合父view的限定以及子view的layout参数,计算子view的测量mode以及最大size
     
     // 3.1 父view是EXACTLY(match_parent/ xxdpi)
        1) 子view childDimension >0, view模式为EXACTLY, size为childDimesion
        2)子view 是MATCH_PARENT, 对应view是EXACTLY, size为剩余空间的size, 子view设置成父view的大小
        3) 子view WRAP_CONTENT  对应view是AT_MOST, size为剩余空间的size, 子view的最大的大小不能超过父view
     
     // 3.2 父view是AT_MOST(wrap_content) 依赖子view
        1) 子view 是childDimession,对应是EXACTLY, size 为childDimesion
        2)子view 是MATCH_PARENT, 对应view是AT_MOST, size为剩余空间的size
        3) 子view WRAP_CONTENT  对应view是AT_MOST, size为剩余空间的size
    
     // 3.2 父view是UNSPECIFIED(wrap_content) 依赖子view
        1) 子view 是childDimession,对应是EXACTLY, size 为childDimesion
        2)子view 是MATCH_PARENT, 对应view是UNSPECIFIED, size为剩余空间的size
        3) 子view WRAP_CONTENT  对应view是UNSPECIFIED, size为剩余空间的size
     
    return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
 }

```

LinearLayout.java
```
void measureVertical(int wSpec, int hSpec){
    // 1. 计算子view的高度
    count = getChildCount();
    for(int i = 0; i < count; i ++){
        // 剔除掉null, 和gone的view
        if(weight方式设置高度[height = 0;weight>] 且高度固定){
            mTotalLenghth = mTotalLength + lp.toMargin + lp.bottomMargin;
        }else{
            if(heigth = 0 && weight >0){
                oldHeight = 0;
                lp.height = WRAP_CONTNET;
            }
        }
        
        // 计算child的宽高以及mode
        measureChildBeforeLayout(child, i, widthMeasureSpec, 0,
                        heightMeasureSpec, usedHeight);
                        

        // 累加计算整体高度
        final int totalLength = mTotalLength;
                mTotalLength = Math.max(totalLength, totalLength + childHeight + lp.topMargin +
                       lp.bottomMargin + getNextLocationOffset(child));
    
        
        // 只有当当前allFillParent 为true, 且为Exactly。,, 
        allFillParent = allFillParent  && lp.width == LayoutParams.MATCH_PARENT;
        if (lp.weight > 0) {
            
            weightedMaxWidth = Math.max(weightedMaxWidth,
                        matchWidthLocally ? margin : measuredWidth);
        } else {
            alternativeMaxWidth = Math.max(alternativeMaxWidth,
                        matchWidthLocally ? margin : measuredWidth);
        }
    }
    
    // 2. 计算LinearLayout 总高度高度
    // 这里useLargestChild为true,表示使用最大的子View的高度来作为自己的高度
    // 这个view赋值 只在 
    if (useLargestChild &&
        (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED)) {
            mTotalLength = 0;

        for (int i = 0; i < count; ++i) {
            final View child = getVirtualChildAt(i);
            if (child == null) {
                mTotalLength += measureNullChild(i);
                    continue;
            }

            if (child.getVisibility() == GONE) {
                    i += getChildrenSkipCount(child, i);
                continue;
            }

            final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
                        child.getLayoutParams();
            // Account for negative margins
            final int totalLength = mTotalLength;
            mTotalLength = Math.max(totalLength, totalLength + largestChildHeight +
                        lp.topMargin + lp.bottomMargin + getNextLocationOffset(child));
        }
    }

    // 累加padding
    mTotalLength += mPaddingTop + mPaddingBottom;
    int heightSize = mTotalLength;
    // 去最小高度和当前高度 两种的最大值
    heightSize = Math.max(heightSize, getSuggestedMinimumHeight());
    // 将size和mode 赋值
    int heightSizeAndState = resolveSizeAndState(heightSize, heightMeasureSpec, 0);
    heightSize = heightSizeAndState & MEASURED_SIZE_MASK;
    

    // 3. 换算weight, 重新计算view
    int delta = heightSize -mTotalLength;
    
    if(delta != 0 && totalWeight > 0){
        float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
        
        for(int i =0; i < count ; i ++){
            // 遍历子view
            float childExtra = lp.weight;
            int share = (int) (childExtra * delta / weightSum);
            weightSum -= childExtra;
            delta -= share;
        
            // 重新计算height
            if (mUseLargestChild && heightMode != MeasureSpec.EXACTLY) {
                    childHeight = largestChildHeight;
            } else if (lp.height == 0 && (!mAllowInconsistentMeasurement
                    || heightMode == MeasureSpec.EXACTLY)) {
                    // This child needs to be laid out from scratch using
                    // only its share of excess space.
                    childHeight = share;
            } else {
                    // This child had some intrinsic height to which we
                    // need to add its share of excess space.
                    childHeight = child.getMeasuredHeight() + share;
            }
            
            // 重建更新计算
            final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
                            Math.max(0, childHeight), MeasureSpec.EXACTLY);
            final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
                            mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin,
                            lp.width);
            child.measure(childWidthMeasureSpec, childHeightMeasureSpe
            
            
        }            
    }
    
    // 4. 设置计算高度以及
    if (!allFillParent && widthMode != MeasureSpec.EXACTLY) {
        maxWidth = alternativeMaxWidth;
    }
    
    maxWidth += mPaddingLeft + mPaddingRight;

    // Check against our minimum width
    maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
    
    setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
            heightSizeAndState);

    if (matchWidth) {
        forceUniformWidth(count, heightMeasureSpec);
    }
}

```

#### View layout 流程

view.java
```
      public void layout(int l, int t, int r, int b) {
        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
            // 是否需要在layout之前重新测量,在测量的时候缓存中存在的时候
            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
        }
    
        // 暂存上一次的layout结果
        int oldL = mLeft;
        int oldT = mTop;
        int oldB = mBottom;
        int oldR = mRight;

        // 根据layout模式,设置viwe的四个顶点的位置, 并根据以前的值判断是否发生变化
        //  return (mLeft != left || mRight != right || mTop != top || mBottom != bottom)
        boolean changed = isLayoutModeOptical(mParent) ?
        setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);

        // 在发生变化了,或者有layout请求的时候重新layout
        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
            // 重写时候的核心方法
            onLayout(changed, l, t, r, b);

            if (shouldDrawRoundScrollbar()) {
                if(mRoundScrollbarRenderer == null) {
                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
                }
            } else {
                mRoundScrollbarRenderer = null;
            }

            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;

            // layout的系统回调
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnLayoutChangeListeners != null) {
                ArrayList listenersCopy =
                        (ArrayList)li.mOnLayoutChangeListeners.clone();
                int numListeners = listenersCopy.size();
                for (int i = 0; i < numListeners; ++i) {
                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
                }
            }
        }

        final boolean wasLayoutValid = isLayoutValid();

        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;

        // 省略。。。
    }

```
对于onLayout的方法实现,以下以FrameLayout作为例子

FrameLayout.java
```
   @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        // 最终实现部分是layoutChildren
        layoutChildren(left, top, right, bottom, false);
    }

    void layoutChildren(int left, int top, int right, int bottom, boolean forceLeftGravity) {
        final int count = getChildCount();
        
        // 计算出父view的layout参数,left,right,top,bottom
        final int parentLeft = getPaddingLeftWithForeground();
        final int parentRight = right - left - getPaddingRightWithForeground();

        final int parentTop = getPaddingTopWithForeground();
        final int parentBottom = bottom - top - getPaddingBottomWithForeground();
        
        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();

                final int width = child.getMeasuredWidth();
                final int height = child.getMeasuredHeight();

                int childLeft;
                int childTop;

                int gravity = lp.gravity;
                if (gravity == -1) {
                    gravity = DEFAULT_CHILD_GRAVITY;
                }

                final int layoutDirection = getLayoutDirection();
                final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
                final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
                
                // 水平计算
                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                    // Gravity 参数的作用在于Layout阶段,根据这个参数来计算child的位置
                    case Gravity.CENTER_HORIZONTAL:
                        childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
                        lp.leftMargin - lp.rightMargin;
                        break;
                    case Gravity.RIGHT:
                        if (!forceLeftGravity) {
                            childLeft = parentRight - width - lp.rightMargin;
                            break;
                        }
                    case Gravity.LEFT:
                    default:
                        childLeft = parentLeft + lp.leftMargin;
                }
                
                // 垂直计算
                switch (verticalGravity) {
                    case Gravity.TOP:
                        childTop = parentTop + lp.topMargin;
                        break;
                    case Gravity.CENTER_VERTICAL:
                        childTop = parentTop + (parentBottom - parentTop - height) / 2 +
                        lp.topMargin - lp.bottomMargin;
                        break;
                    case Gravity.BOTTOM:
                        childTop = parentBottom - height - lp.bottomMargin;
                        break;
                    default:
                        childTop = parentTop + lp.topMargin;
                }
                
                // 递归下去
                child.layout(childLeft, childTop, childLeft + width, childTop + height);
            }
        }
    }
```

#### view Draw流程
ViewRootImpl.java
```
 private void performDraw() {
    
        try {
            boolean canUseAsync = draw(fullRedrawNeeded);
            if (usingAsyncReport && !canUseAsync) {
                mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(null);
                usingAsyncReport = false;
            }
        } finally {
            mIsDrawing = false;
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
}

// 核心
private boolean draw(boolean fullRedrawNeeded) {
        Surface surface = mSurface;
        if (!surface.isValid()) {
            return false;
        }

        // 获取mDirty,需要重新绘制的区域
        final Rect dirty = mDirty;
        if (mSurfaceHolder != null) {
            dirty.setEmpty();
            if (animating && mScroller != null) {
                mScroller.abortAnimation();
            }
            return false;
        }
        
        // 第一次绘制流程需要绘制所有的区域
        if (fullRedrawNeeded) {
            mAttachInfo.mIgnoreDirtyState = true;
            dirty.set(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
        }
        
        
        
        mAttachInfo.mDrawingTime =
                mChoreographer.getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;

        boolean useAsyncReport = false;
        if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
            if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {
                // If accessibility focus moved, always invalidate the root.
                boolean invalidateRoot = accessibilityFocusDirty || mInvalidateRootRequested;
                mInvalidateRootRequested = false;

                // Draw with hardware renderer.
                mIsAnimating = false;

                if (mHardwareYOffset != yOffset || mHardwareXOffset != xOffset) {
                    mHardwareYOffset = yOffset;
                    mHardwareXOffset = xOffset;
                    invalidateRoot = true;
                }

                if (invalidateRoot) {
                    mAttachInfo.mThreadedRenderer.invalidateRoot();
                }

                dirty.setEmpty();

                // Stage the content drawn size now. It will be transferred to the renderer
                // shortly before the draw commands get send to the renderer.
                final boolean updated = updateContentDrawBounds();

                if (mReportNextDraw) {
                    // report next draw overrides setStopped()
                    // This value is re-sync'd to the value of mStopped
                    // in the handling of mReportNextDraw post-draw.
                    mAttachInfo.mThreadedRenderer.setStopped(false);
                }

            
            } else {
              
                // 核心方法,
                if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset,
                        scalingRequired, dirty, surfaceInsets)) {
                    return false;
                }
            }
        }
    }

 private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
            boolean scalingRequired, Rect dirty, Rect surfaceInsets) {

        final Canvas canvas;

       
        int dirtyXOffset = xoff;
        int dirtyYOffset = yoff;
        if (surfaceInsets != null) {
            dirtyXOffset += surfaceInsets.left;
            dirtyYOffset += surfaceInsets.top;
        }

        try {
            dirty.offset(-dirtyXOffset, -dirtyYOffset);
            final int left = dirty.left;
            final int top = dirty.top;
            final int right = dirty.right;
            final int bottom = dirty.bottom;
            //锁定绘制区域
            canvas = mSurface.lockCanvas(dirty);

            // The dirty rectangle can be modified by Surface.lockCanvas()
            //noinspection ConstantConditions
            if (left != dirty.left || top != dirty.top || right != dirty.right
                    || bottom != dirty.bottom) {
                attachInfo.mIgnoreDirtyState = true;
            }

          d
            canvas.setDensity(mDensity);
        } catch (Surface.OutOfResourcesException e) {
            handleOutOfResourcesException(e);
            return false;
        } catch (IllegalArgumentException e) {
            Log.e(mTag, "Could not lock surface", e);
            mLayoutRequested = true;    // ask wm for a new surface next time.
            return false;
        } finally {
            dirty.offset(dirtyXOffset, dirtyYOffset);  // Reset to the original value.
        }

        try {
        
            try {
                canvas.translate(-xoff, -yoff);
                if (mTranslator != null) {
                    mTranslator.translateCanvas(canvas);
                }
                canvas.setScreenDensity(scalingRequired ? mNoncompatDensity : 0);
                attachInfo.mSetIgnoreDirtyState = false;
                
                # 此处mView 为decorView, 最终调用View.java##draw方法
                mView.draw(canvas);

                drawAccessibilityFocusedDrawableIfNeeded(canvas);
            } finally {
                if (!attachInfo.mSetIgnoreDirtyState) {
                    // Only clear the flag if it was not set during the mView.draw() call
                    attachInfo.mIgnoreDirtyState = false;
                }
            }
        }
        return true;
    
```

View.java 回到draw方中去
```
 public void draw(Canvas canvas) {
        final int privateFlags = mPrivateFlags;
        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
        
        // 按照顺序
        //     1. Draw the background
        //     2. 保存当前图层信息不一定执行)
        //      3. 绘制view 内容,通过调用onDraw
        //      4.  dispatchDraw, 绘制子view
        //      5. 绘制View fade的便于,类似阴影小姑
        //      6. 绘制View装饰物,例如滚动条

     
        // 1. 绘制背景

        if (!dirtyOpaque) {
            drawBackground(canvas);
        }

        // 2,保存状态
        final int viewFlags = mViewFlags;
        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
        
        if (!verticalEdges && !horizontalEdges) {
            // 3. 绘制内容, 自定义View绘制
            if (!dirtyOpaque) onDraw(canvas);

            // 4. 绘制子view
            dispatchDraw(canvas);

            drawAutofilledHighlight(canvas);

            // Overlay is part of the content and draws beneath Foreground
            if (mOverlay != null && !mOverlay.isEmpty()) {
                mOverlay.getOverlayView().dispatchDraw(canvas);
            }

            // Step 6, 绘制装饰物
            onDrawForeground(canvas);
            return;
        }
    }
```
ViewGroup 绘制子View
```
protected void dispatchDraw(Canvas canvas) {
        boolean usingRenderNodeProperties = canvas.isRecordingFor(mRenderNode);
        final int childrenCount = mChildrenCount;
        final View[] children = mChildren;
        int flags = mGroupFlags;

       // 遍历调用子view
        for (int i = 0; i < childrenCount; i++) {
            while (transientIndex >= 0 && mTransientIndices.get(transientIndex) == i) {
                final View transientChild = mTransientViews.get(transientIndex);
                if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||
                        transientChild.getAnimation() != null) {
                    more |= drawChild(canvas, transientChild, drawingTime);
                }
                transientIndex++;
                if (transientIndex >= transientCount) {
                    transientIndex = -1;
                }
            }
        }
}

  protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        // 子view draw方
        return child.draw(canvas, this, drawingTime);
}

```
最终会调用子view 的draw方法
```
boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {

    //省略...
    
    if (!drawingWithDrawingCache) {
        if (drawingWithRenderNode) {
            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
            ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
        } else {
            // Fast path for layouts with no backgrounds
            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                dispatchDraw(canvas);
            } else {
                draw(canvas);
            }
        }
    } else if (cache != null) {
        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
        if (layerType == LAYER_TYPE_NONE) {
            // no layer paint, use temporary paint to draw bitmap
            Paint cachePaint = parent.mCachePaint;
            if (cachePaint == null) {
                cachePaint = new Paint();
                cachePaint.setDither(false);
                parent.mCachePaint = cachePaint;
            }
            cachePaint.setAlpha((int) (alpha * 255));
            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
        } else {
            // use layer paint to draw the bitmap, merging the two alphas, but also restore
            int layerPaintAlpha = mLayerPaint.getAlpha();
            mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
            canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
            mLayerPaint.setAlpha(layerPaintAlpha);
        }
    }

}
```

你可能感兴趣的:(android源码之View绘制)