onMeasure被执行两次原理解析
目录
什么情况下会onMeasure会执行?为什么onMeasure会被执行两次?分析外部是如何多次调用measure方法的什么情况下会onMeasure会执行?
进入View
的measure
方法:
void measure(){ boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec || heightMeasureSpec != mOldHeightMeasureSpec; boolean isSepcExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY; boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec); final boolean needsLayout = specChanged && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize); if(forceLayout || needLayout){ int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key); if (cacheIndex < 0 || sIgnoreMeasureCache) { onMeasure(widthMeasureSpec, heightMeasureSpec); mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; } else { long value = mMeasureCache.valueAt(cacheIndex); setMeasuredDimensionRaw((int) (value >> 32), (int) value); mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; } } }
什么时候forceLayout=true
:
requestLayout
调用forceRequestLayout
什么时候needsLayout=true
:
(资料图片仅供参考)
什么时候调用了onMeasure>
方法:
forceLayouy=true
或者mMeasureCache
没有当前的缓存
总结:
当调用了requestLayout
一定会测发重测过程.当forceLayout=false
的时候会去判断mMeasureCache
值.现在研究下这个mMeasureCache
class View{ LongSparseLongArray mMeasureCache; void measure(widthSpec,heightSpec){ --- long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL; int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key); if(cacheIndex<0){ onMeasure(widthSpec,heightSpec); } mOldWidthMeasureSpec = widthMeasureSpec; mOldHeightMeasureSpec = heightMeasureSpec; mMeasureCache.put(key,widhSpec|heightSpec); --- } }
这里可以看到oldWidthMeasureSpec
和mMeasureCache
都是缓存上一次的值,那他们有什么不同呢?不同点就是,oldWidthMeasureSpec>
不仅仅缓存了测量的spec
模式而且缓存了size
.但是mMeasureCache
只缓存了size
.从这行代码可以看出:
long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
这里一同运算就为了排除掉spec
造成的影响.
//不信你可以试下下面的代码 public class Test { public static void main(String[] args) { long widthMeasureSpec = makeMeasureSpec(10,0); long heightMeasureSpec = makeMeasureSpec(20,0); long ss = widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL; System.out.println("=========="+ss); } private static final int MODE_MASK = 0x3 << 30; public static int makeMeasureSpec(int size, int mode) { return (size & ~MODE_MASK) | (mode & MODE_MASK); } } //42949672980 //42949672980 //42949672980
什么时候mPrivateFlags
会被赋值PFLAG_FORCE_LAYOUT
.
在view viewGrouup
的构造函数里面会主动赋值一次,然后在ViewGroup.addView
时候会给当前View
的mProvateFlags
赋值PFLAG_FORCE_LAYOUT
.
为什么onMeasure会被执行两次?
void measure(int widthMeasureSpec,int heightMeasureSpec){ ---- boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; if(forceLayout | needsLayout){ onMeasure() } ---- } public void layout(int l, int t, int r, int b){ --- mPrivateFlags &= ~PFLAG_FORCE_LAYOUT; --- }
在第一次触发到measure
方法时,forceLayoyt=true needsLayout=true
,但是layout
方法还没触发到.
在第二次触发到measure>
方法时,forceLayout=true needsLayout=false
,所以还是会进入onMeasure
方法.这次会执行layout
方法.然后我们在下次的时候forceLayout
就等于false
了.上面的这一段分析是分析的measure
内部如何防止多次调用onMeasure
.
分析外部是如何多次调用measure方法的
在Activity
执行到onResume
生命周期的时候,会执行WindowManager.addView
操作,WindowManager
的具体实现类是WindowManagerImpl
然后addView
操作交给了代理类WindowManagerGlobal
,然后在WindowManagerGlobal
的addView
里面执行了ViewRootImpl.setView
操作(ViewRootImpl
对象也是在这个时候创建的),在ViewRootImpl
会主动调用一次requestLayout
,也就开启了第一次的视图 测量 布局 绘制.
在setView
的时候主动调用了一次ViewRootImpl.requestLayout
,注意这个requestLayout
是ViewRootImpl
的内部方法,和view viewGroup
那些requestLayout
不一样.在ViewRootImpl.requestLayout
内部调用了performTraversals
方法:
class ViewRootImpl{ void performTraversals(){ if(layoutResuested){ //标记1 windowSizeMayChanged |= measureHierarchy(host,lp,res,desiredWindowWidth,desiredWindowHeight); } //标记2 performMeasure() performLayout() } void measureHierarchy(){ performMeasure() } }
从ViewRootImpl
的执行逻辑你可以看出,在执行performLayout
之前,他自己就已经调用了两次performMeasure
方法.所以你现在就知道为啥了.
以上就是onMeasure被执行两次原理解析的详细内容,更多关于onMeasure被执行两次的资料请关注脚本之家其它相关文章!
相关新闻
- onMeasure被执行两次原理解析
- 港股异动 | 中国黄金国际(02099)跌超3%领跌黄金股 就业数据强劲助长加息预期 美债利率反弹令金价承压
- 为女足姑娘们加油!球迷守候在机场,为中国女足世界杯之旅送行
- 中威电子(300270.SZ):以太网交换机目前没有应用在数据中心上
- 近5成青少年心理疾病患者为抑郁症,并呈逐年攀升趋势
- 王导:黄金1920空暴跌获利,1910直接空
- 法国之后,美国也乱了!首都15分钟发生3次爆炸,嫌疑人逍遥法外
- 绿城管理控股(09979.HK):上半年新拓代建项目代建费预估51.2亿 同比增长26.3%
- 热惨咯!想要健脾清热,小暑“三宝”吃起来
- 推特就Threads相关问题给Meta发律师函
- 平顶山亮证男子新进展:亮证男子徐科长被免职,交警张队长被处分
- 被冷落的NBA球星
- 各地采取积极举措帮助高校毕业生就业
- GPLP投融资:达闼机器人获10亿元 前海粤十获6.2亿元
- 加科思创新药被“退货”,可能会成为行业里程碑
- 世界上最大的嘴唇(世界上最大的嘴)
- 时间过半 任务过半 广汽汇理上半年业绩飘红
- 长期借款一般性保护条款?
- 浙江世宝涨10.03% 机构净卖出1.22亿元
- 汇丰控股7月5日斥资1.45亿港元回购235万股