设置View可见后同线程完成测量,为何View.getHeight()仍返回0?
为什么设置View可见后立即获取高度返回0,且Android不同步完成测量布局?
嘿,这个问题问到点子上了——我当初刚学Android的时候也被这个逻辑绕晕过!给你把事儿掰得明明白白:
首先,为啥setVisibility(View.VISIBLE)后getHeight()返回0?
当你调用setVisibility()的时候,Android并没有立刻执行测量(measure)、布局(layout)这些核心步骤,它只是给这个视图打上了「需要更新」的标记,然后把这个更新请求塞进UI线程的消息队列里排队。
而你的int viewHeight = view.getHeight();是紧接着同步执行的,这时候测量布局连启动都还没启动呢,自然拿到的是视图的默认初始值0。
核心疑问:为啥Android不在同线程里同步完成测量布局?
这得从Android UI线程的工作逻辑说起:
- Android的UI线程是靠**消息循环(Message Loop)**跑起来的,所有UI相关的操作(视图更新、触摸事件、按键响应等)全都是排队进消息队列,按顺序处理的。
- 如果每次调用
setVisibility()、setLayoutParams()这类修改视图的方法,就立刻同步触发测量布局,会捅两个大娄子:- 性能雪崩:假设你连续改了好几个视图属性(先开可见性,再调宽高,再改内边距),每改一次就跑一遍完整的测量布局,这会造成大量重复计算,UI直接卡成PPT。
- 阻塞UI线程:复杂嵌套视图的测量布局本身就挺耗时的,如果在同步代码里硬塞这个操作,会直接卡住当前的消息处理,轻则界面卡顿,重则触发ANR(应用无响应)。
所以Android特意设计成延迟批量处理:先把所有视图更新请求攒起来,等你当前这段同步代码执行完、跳出当前消息处理后,再在下一轮消息循环里统一执行测量、布局、绘制全流程——既保证了性能,又不会把UI线程堵死。
再给你补两个实用的获取高度写法(除了你知道的ViewTreeObserver)
- 用View的
post()方法:把获取高度的代码放到消息队列尾部,等测量布局完成后再执行:view.setVisibility(View.VISIBLE); view.post(new Runnable() { @Override public void run() { int viewHeight = view.getHeight(); // 这里就能拿到正确高度啦 } }); - 自定义View重写
onLayout():如果是自己写的View,直接在onLayout()里拿高度就行——这个方法就是布局完成后专门回调的:@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (changed) { int viewHeight = getHeight(); // 处理高度相关逻辑 } }
内容的提问来源于stack exchange,提问作者Sundaravel
相关产品推荐
相关产品推荐

