final class TraversalRunnable implements Runnable { @Override public void run() { doTraversal(); } } final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
这个Runnable任务里面就调用了一个方法doTraversal(执行View的遍历)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
void doTraversal() { if (mTraversalScheduled) { mTraversalScheduled = false; mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) { Debug.startMethodTracing("ViewAncestor"); }
performTraversals();
if (mProfile) { Debug.stopMethodTracing(); mProfile = false; } } }
private static int getRootMeasureSpec(int windowSize, int rootDimension) { // 声明测量的MeasureSpec int measureSpec; // 根据LayoutParams的参数来确定DecorView的 switch (rootDimension) { // 如果是MATCH_PARENT 很好理解。直接确定尺寸为屏幕尺寸 case ViewGroup.LayoutParams.MATCH_PARENT: // Window can't resize. Force root view to be windowSize. measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY); break; // 如果是WRAP_CONTENT 那么设置测量规格为AT_MOST。 case ViewGroup.LayoutParams.WRAP_CONTENT: // Window can resize. Set max size for root view. measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST); break; default: // Window wants to be an exact size. Force root view to be that size. // 如果是申请的具体的尺寸值,那么就设置为具体的尺寸值。规格为EXACTLY measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY); break; } return measureSpec; }
* // 我们先看一下这个方法传入的参数: * 父View的MeasureSpec * 父View的总pading = (父View声明的pading+子View的margin+已经用掉的width) * 子View声明的宽度 */ public static int getChildMeasureSpec(int spec, int padding, int childDimension) { // 根据父View的MeasureSpec来获取测量规格和尺寸 int specMode = MeasureSpec.getMode(spec); int specSize = MeasureSpec.getSize(spec); // 我们计算子View可用的尺寸大小。就是父View的测量尺寸-父View的总padding.剩余的就是View的可用尺寸 int size = Math.max(0, specSize - padding); // 声明子View的测量尺寸和测量规格 int resultSize = 0; int resultMode = 0; // 我们根据父View的测量模式来一次计算子View的测量模式 // 我们可以用表格来进行来归纳总结 switch (specMode) { /// 如果父View是确切尺寸 // Parent has imposed an exact size on us case MeasureSpec.EXACTLY: // 如果子View的测量尺寸是确切值, if (childDimension >= 0) { // 如果子View的尺寸大于0 ,则设置 resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size. So be it. // 如果子View的尺寸是MATCH_PARENT 则子View等于占满父View的剩余尺寸 resultSize = size; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size. It can't be // bigger than us. // 如果子View的尺寸是WRAP_CONTENT 则子View为AT_MOST 小于等于size resultSize = size; resultMode = MeasureSpec.AT_MOST; } break;
// Parent has imposed a maximum size on us // 如果父View的测量规格是AT_MOST case MeasureSpec.AT_MOST: if (childDimension >= 0) { // Child wants a specific size... so be it // 如果子View的尺寸大于0 ,则设置 resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { // 如果子View的尺寸是MATCH_PARENT 则子View等于占满父View的剩余尺寸 // Child wants to be our size, but our size is not fixed. // Constrain child to not be bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } else if (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size. It can't be // bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } break;
// Parent asked to see how big we want to be case MeasureSpec.UNSPECIFIED: if (childDimension >= 0) { // Child wants a specific size... let him have it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size... find out how big it should // be resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size; resultMode = MeasureSpec.UNSPECIFIED; } else if (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size.... find out how // big it should be resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size; resultMode = MeasureSpec.UNSPECIFIED; } break; } //noinspection ResourceType return MeasureSpec.makeMeasureSpec(resultSize, resultMode); }