两个view:

一个是系统默认的FrameLayout,  A

一个是自己自定义的MyView extends View,重载了onMeasure函数(): B

  1. @Override
  2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  3. // TODO Auto-generated method stub
  4. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  5. // Log.e(TAG, "onMeasure " + MeasureSpec.getSize(widthMeasureSpec)
  6. //      + " " + MeasureSpec.getSize(heightMeasureSpec));
  7. setMeasuredDimension(MeasureSpec.makeMeasureSpec(mW-=10, MeasureSpec.EXACTLY),
  8. MeasureSpec.makeMeasureSpec(mH-=10, MeasureSpec.EXACTLY));
  9. }
	@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Log.e(TAG, "onMeasure " + MeasureSpec.getSize(widthMeasureSpec)
// + " " + MeasureSpec.getSize(heightMeasureSpec));
setMeasuredDimension(MeasureSpec.makeMeasureSpec(mW-=10, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mH-=10, MeasureSpec.EXACTLY));
}

逻辑很简单,每次只要B的onMeasure被触发,那么B的尺寸就原来小10.

A包含B,

几个测试case: (measure() 是final的,无法覆盖,不过B的measure()应该是每次被调到的)

1. A.requestLayout();                                    不会调用到B.onMeasure() 和 B.onLayout(), 会调用B.layout() (注意连draw()都没有被调到,这意味着B被A认为完全没变,不需要重绘)

2. B.forceLayout(); A.requestLayout()           会调用到B的.onMeasure() 和 onLayout() 以及 layout(), draw(), onDraw()

3. B.requestLayout()                                      会调用到B的.onMeasure() 和 onLayout() 以及 layout(),draw(), onDraw()

4. B.invalidate()                                               B的layout(), onLayout() 和 onMeasure() 没有被调到,只有 draw() 和 onDraw() 被调到.

5  A.invalidate()                                               B的所有函数都不会被调到.

这个结果也符合code的逻辑,forceLayout()如果注释说的一样,是在下一次layout bypass 的过程(自己不会发起一次layout bypass)中,会强制的重新onMeasure和onLayout()

而requestLayout() 除了干forceLayout()的事情将自己的FORCE_LAYOUT标志位设上外,还会发起一次layout pass,

在layout bypass 从 A 传到 B时,虽然 A 的 onMeasure() 和 onLayout() 会调用 B 的 measure() 和 layout(), 但是,因为 B的layout状态没有什么改变,因此

onMeasure()和 onLayout()不会被调用.

在当前4.4的code:

  1. public void forceLayout() {
  2. ................................................
  3. mPrivateFlags |= PFLAG_FORCE_LAYOUT;
  4. mPrivateFlags |= PFLAG_INVALIDATED;
  5. }
  6. public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
  7. ...............................................................
  8. if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
  9. .......................................................
  10. int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
  11. mMeasureCache.indexOfKey(key);
  12. if (cacheIndex < 0 || sIgnoreMeasureCache) {
  13. ..................................................
  14. onMeasure(widthMeasureSpec, heightMeasureSpec);
  15. mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
  16. } else {
  17. long value = mMeasureCache.valueAt(cacheIndex);
  18. // Casting a long to int drops the high 32 bits, no mask needed
  19. setMeasuredDimension((int) (value >> 32), (int) value);
  20. mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
  21. }
  22. ......................................................................................
  23. mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
  24. }
  25. .............................................................................
  26. }
  27. public void layout(int l, int t, int r, int b) {
  28. .....................................................
  29. if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
  30. onLayout(changed, l, t, r, b);
  31. mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
  32. ...................................................................
  33. }
  34. mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
  35. mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
  36. }
public void forceLayout() {
     ................................................
        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
        mPrivateFlags |= PFLAG_INVALIDATED;
    } public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
...............................................................
if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
.......................................................
int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
mMeasureCache.indexOfKey(key);
if (cacheIndex < 0 || sIgnoreMeasureCache) {
..................................................
onMeasure(widthMeasureSpec, heightMeasureSpec);
  mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
} else {
long value = mMeasureCache.valueAt(cacheIndex);
// Casting a long to int drops the high 32 bits, no mask needed
setMeasuredDimension((int) (value >> 32), (int) value);
mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
}
......................................................................................
mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
}
.............................................................................
} public void layout(int l, int t, int r, int b) {
        .....................................................
        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
            onLayout(changed, l, t, r, b);
            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;            ...................................................................
        }         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
    }

可见forceLayout()可以导致onMeasure() 和 onLayout(). 而requestLayout() 干的事情比forceLayout()只多不少.

View的forceLayout后面一般会紧跟着View的measure(), 这样可以把view的measuredSize 通过 setMeasuredDimension 设上.

而PFLAG_INVALIDATED 这个flag 应该是标记 重绘的。

而requestLayout()/forceLayout() 设置的另一个flag PFLAG_FORCE_LAYOUT,也一定可以在measure()中 将PFLAG_LAYOUT_REQUIRED flag给打上,

而PFLAG_LAYOUT_REQUIRED 则是可以保证了在调用 layout()函数时,onLayout() 函数会被调用到.

还有一点,之前没有仔细看, View的measure(A, B) 函数:

  1. 如果有PFLAG_FORCE_LAYOUT 或者 本次的measure的尺寸 A, B 和 之前的尺寸不一样
  2. if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
  3. widthMeasureSpec != mOldWidthMeasureSpec ||
  4. heightMeasureSpec != mOldHeightMeasureSpec) {
  5. ........................................................
  6. 这一步其实是从之前的MeasureCache里找是否存在 和 本次的measure尺寸一致的 cache
  7. int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
  8. mMeasureCache.indexOfKey(key);
  9. 如果没有找到,那么就调用onMeasure, 一般来说,调用了onMeasure才能真正的setMeasuredDimension
  10. if (cacheIndex < 0 || sIgnoreMeasureCache) {
  11. // measure ourselves, this should set the measured dimension flag back
  12. onMeasure(widthMeasureSpec, heightMeasureSpec);
  13. mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
  14. } else {
  15. 如果找到有cache,那么就将cache的值 设为 setMeasuredDimension
  16. long value = mMeasureCache.valueAt(cacheIndex);
  17. // Casting a long to int drops the high 32 bits, no mask needed
  18. setMeasuredDimension((int) (value >> 32), (int) value);
  19. mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
  20. }
  21. }
  22. ..............................................
  23. mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
  24. ..............................................
  25. mOldWidthMeasureSpec = widthMeasureSpec;
  26. mOldHeightMeasureSpec = heightMeasureSpec;
  27. mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
  28. (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
	       如果有PFLAG_FORCE_LAYOUT 或者 本次的measure的尺寸 A, B 和 之前的尺寸不一样
if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
widthMeasureSpec != mOldWidthMeasureSpec ||
heightMeasureSpec != mOldHeightMeasureSpec) { ........................................................ 这一步其实是从之前的MeasureCache里找是否存在 和 本次的measure尺寸一致的 cache
int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
mMeasureCache.indexOfKey(key);
如果没有找到,那么就调用onMeasure, 一般来说,调用了onMeasure才能真正的setMeasuredDimension
if (cacheIndex < 0 || sIgnoreMeasureCache) {
// measure ourselves, this should set the measured dimension flag back
onMeasure(widthMeasureSpec, heightMeasureSpec);
mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
} else {
如果找到有cache,那么就将cache的值 设为 setMeasuredDimension
long value = mMeasureCache.valueAt(cacheIndex);
                 // Casting a long to int drops the high 32 bits, no mask needed
                 setMeasuredDimension((int) (value >> 32), (int) value);
                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
}
} ..............................................
mPrivateFlags |= PFLAG_LAYOUT_REQUIRED; ..............................................
mOldWidthMeasureSpec = widthMeasureSpec;
         mOldHeightMeasureSpec = heightMeasureSpec;          mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension 

这说明调用measure(A, B), 只要尺寸变化,都会影响 MeasuredHeight/Width

借鉴:http://blog.csdn.net/fyfcauc/article/details/41895509

一个 forceLayout() 和 requestLayout() 的测试的更多相关文章

  1. Huxley 是一个用于Web应用 UI 测试的工具

    Huxley 是一个用于Web应用 UI 测试的工具,由  Pete Hunt 和 Maykel Loomans 用 Python 开发. UI 测试比较令人头疼. UI测试不好写,而且很容易失效: ...

  2. Selenium也是一个用于Web应用程序测试的工具

    Selenium也是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包括IE.Mozilla Firefox.Mozilla Suite ...

  3. 一个类似于postman的协议测试工具

    协议测试工具使用postman相当便捷,不过有一个问题,就是每个人都要装一个这个东西,并且测试文件导来导去,还是觉得麻烦了点. 最重要的是postman不能修改,有一些定制功能postman明显力不从 ...

  4. 一个好用的压力测试工具tsung

    一个好用的压力测试工具tsung          前段时间一直在忙各种事情,快三周没弄过引擎了,今天有点时间,正好之前写的服务器引擎也到了收尾测试的阶段,于是就研究了下怎么测试服务器压力.      ...

  5. 一个"如何使用示波器安全测试接市电电路板"的问题

    最近犯了一个错误测试操作: 测试场景:直接从市电插座取电接入3W非隔离开关电源电路板,使用示波器测试输出电压,此时示波器通过另外一个插座直接从市电取电 测试后果:在将示波器接到输出负极的一瞬间,漏电保 ...

  6. ios如何一个证书多台设备测试

    在苹果开发者网站申请的证书,是授权mac设备的开发或者发布的证书,这意味着一个设备对应一个证书,但是99美元账号只允许生成3个发布证书,两个开发证书,这满足不了多mac设备的使用,使用p12文件可以解 ...

  7. 不会用ant打包、部署项目的工程师,不是一个好程序员(测试)

    副标题:利用ant脚本 自动构建svn增量/全量 系统程序升级包 首先请允许我这样说,作为开发或测试,你一定要具备这种本领.你可以手动打包.部署你的工程,但这不是最好的方法.最好的方式就是全自动化的方 ...

  8. 实例--post请求,完成一个抽奖程序概率的测试

    一个web项目测试,测试抽奖概率的正确性,写了一个小代码,验证概率 post和get请求的一个工具类 package kankan_interface; import java.io.IOExcept ...

  9. 一个基于集成jenkins的测试平台

    (一)先看测试业务的情况: 有各种各样的任务包括代码构建.部署搭建.单元测试.功能自动化测试(包括许多模块的功能自动化测试,有十几个居多),性能测试.正确性验证:复杂一点的是这些任务在不同的测试阶段中 ...

随机推荐

  1. [重磅]Deep Forest,非神经网络的深度模型,周志华老师最新之作,三十分钟理解!

    欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术感兴趣的同学加入. 深度学习最大的贡献,个人认为就是表征 ...

  2. STL中stack/queue/map以及Boost unordered_map 的使用方法

    一.stackstack 模板类的定义在<stack>头文件中.stack 模板类需要两个模板参数,一个是元素类型,一个容器类型,但只有元素类型是必要的,在不指定容器类型时,默认的容器类型 ...

  3. MacBook Pro查找已安装的python目录

    MacBook Pro上下载的python安装后,发现查找目录无从下手,如下则是给出解决方案. 1.可下载pip进行安装,安装完成后,打开终端,输入:pip 并回车,则看到pip安装成功 2.再次输入 ...

  4. springcloud 出现unavailable-replicas

    springcloud 出现unavailable-replicas 原因: 1. 部分服务不可用 2. 直接使用了ip地址作为hostname application.properties # 不能 ...

  5. [实战]MVC5+EF6+MySql企业网盘实战(10)——新建文件夹

    写在前面 上篇文章更新了编辑了文件名的操作,本片文章将实现新建文件夹的功能. 系列文章 [EF]vs15+ef6+mysql code first方式 [实战]MVC5+EF6+MySql企业网盘实战 ...

  6. <<Javascript Patterns>>阅读笔记 – 第3章 字面量和构造函数

    对象字面量 首先给出对象字面量的定义语法: 1. 将对象定义在一对括号中(左大括号“{”和右大括号”}”) 2. 对象中以逗号分隔属性和方法. 每个属性或方法以key-value的形式出现, key和 ...

  7. 在 Ubuntu 系统安装 Redi laravel 5.2 引入第三方类

    composer 安装类依赖包 很受用 也很方便 但是要是一个有一定规模的公司技术团队 因为要照顾大局 还是引入类好些 下面是引入类的方法 1.首先在app目录下创建一个新的文件夹,命名Tools(可 ...

  8. CodeForces 805B 3-palindrome

    构造. $bbaabbaabbaa......$输出前$n$个即可,这样不需要用到$c$,而且任意相邻三个都不会是回文. #include <cstdio> #include <cm ...

  9. Python开发基础-Day32 进程间通信、进程池、协程

    进程间通信 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 进程队列queue 不同于线程queue,进程 ...

  10. esxi上引起vm绑定浮动IP无法和外面通信

    在vmware esxi环境通过创建VM安装完成openstack之后,发现创建Instance后网络不通,经过多方面排查,最后确定是vmware esxi标准交换机拒绝“混杂模式”所致,故打开“混杂 ...