大家好,我是考100分的小小码 ,祝大家学习进步,加薪顺利呀。今天说一说什么是viewmodel_体系包括什么,希望您对编程的造诣更进一步.
本文已参与「新人创作礼」活动,一起开启掘金创作之路。
MeasureSpec
是View
的内部类,MeasureSpec
封装了从父级传递到子级的测量要求。每个 MeasureSpec
代表对宽度或高度的要求。 MeasureSpec
由大小和模式两部分组成。
更详细的说明请看 Google官方文档
下面是MeasureSpec
的源码:(基于Android 12
)
public static class MeasureSpec {
private static final int MODE_SHIFT = 30;
private static final int MODE_MASK = 0x3 << MODE_SHIFT;
public static final int UNSPECIFIED = 0 << MODE_SHIFT;
public static final int EXACTLY = 1 << MODE_SHIFT;
public static final int AT_MOST = 2 << MODE_SHIFT;
public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode) {
if (sUseBrokenMakeMeasureSpec) {
return size + mode;
} else {
return (size & ~MODE_MASK) | (mode & MODE_MASK);
}
}
public static int makeSafeMeasureSpec(int size, int mode) {
if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
return 0;
}
return makeMeasureSpec(size, mode);
}
public static int getMode(int measureSpec) {
return (measureSpec & MODE_MASK);
}
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
static int adjust(int measureSpec, int delta) {
final int mode = getMode(measureSpec);
int size = getSize(measureSpec);
if (mode == UNSPECIFIED) {
return makeMeasureSpec(size, UNSPECIFIED);
}
size += delta;
if (size < 0) {
Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
") spec: " + toString(measureSpec) + " delta: " + delta);
size = 0;
}
return makeMeasureSpec(size, mode);
}
public static String toString(int measureSpec) {
int mode = getMode(measureSpec);
int size = getSize(measureSpec);
StringBuilder sb = new StringBuilder("MeasureSpec: ");
if (mode == UNSPECIFIED)
sb.append("UNSPECIFIED ");
else if (mode == EXACTLY)
sb.append("EXACTLY ");
else if (mode == AT_MOST)
sb.append("AT_MOST ");
else
sb.append(mode).append(" ");
sb.append(size);
return sb.toString();
}
}
从源码可以看出,它代表了32位int
值,其中高2位代表mode
,低30位代表size
。mode
指测量模式,size
指测量值。mode
有3种模式:
-
UNSPECIFIED
:未指定模式,父View
没有对子View
施加任何限制。它可以是任何它想要的大小。 -
EXACTLY
:精确模式,父View
已经确定了子View
的确切尺寸。无论子View
想要多大,都将获得这些界限。 -
AT_MOST
:最大模式,子View
可以根据需要达到指定的最大的大小。
makeMeasureSpec
用来保存宽和高的信息,getMode
用来获取测量模式,getSize
用来获取测量大小。
MeasureSpec
受自身LayoutParams
和父View
的MeasureSpec
共同影响。作为顶层View
的DecorView
来说,其并没有父View
,那它的MeasureSpec
是如何得来的呢?我们回到ViewRootImpl
的performTraversals
方法:
if (!mStopped || wasReportNextDraw) {
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
(relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
|| mHeight != host.getMeasuredHeight() || dispatchApplyInsets ||
updatedConfiguration) {
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);//1
int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
if (DEBUG_LAYOUT) Log.v(mTag, "Ooops, something changed! mWidth="
+ mWidth + " measuredWidth=" + host.getMeasuredWidth()
+ " mHeight=" + mHeight
+ " measuredHeight=" + host.getMeasuredHeight()
+ " dispatchApplyInsets=" + dispatchApplyInsets);
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);//2
再看注释1处的getRootMeasureSpec
方法:
private static int getRootMeasureSpec(int windowSize, int rootDimension) {
int measureSpec;
switch (rootDimension) {
case ViewGroup.LayoutParams.MATCH_PARENT:
measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);
break;
case ViewGroup.LayoutParams.WRAP_CONTENT:
measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);
break;
default:
measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);
break;
}
return measureSpec;
}
第一个参数windowSize
指窗口的尺寸,所以对于DecorView
来说,它的MeasureSpec
由自身的LayoutParams
和窗口的尺寸决定,这一点和普通的View
是不同的。 再回到上面看注释2处的performMeasure
方法:
private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
if (mView == null) {
return;
}
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
try {
mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);//1
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
注释1处调用了mView.measure
方法,进入了view
的measure
流程。
学习更多知识,请关注我的个人博客:droidYu
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13898.html