震惊!Android开发竟这样获取View宽高?View.post()原理大揭秘

Android开发竟这样获取View宽高?View.post()原理大揭秘

问题背景

在某些场景下,我们需要在Activity的onCreate方法中获取View的宽高,如果我们直接使用getMeasuredHeight()或是getMeasuredWidth()去获取,得到的值都是0

解决方案

  • 推荐方案:View.post() ✅ 自动处理视图状态,代码简洁
  • ViewTreeObserver
  • 通过MeasureSpec自行测量宽高
  • 使用postDelay()延迟一段时间(不推荐,存在时序风险)
View.post()用法案例
java 复制代码
// 在Activity的onCreate()中
View myView = findViewById(R.id.my_view);
myView.post(new Runnable() {
    @Override
    public void run() {
        int width = myView.getWidth();
        int height = myView.getHeight();
        Log.d("ViewSize", "Width: " + width + ", Height: " + height);
    }
});
View.post()原理要点

核心机制HandlerActionQueue + AttachInfo 双通道保障

  1. ▶️ Attach前:通过HandlerActionQueue缓存任务
  2. ▶️ Attach后:通过主线程Handler立即执行
  3. 🚨 关键限制:必须依附View树才能生效(单独new的View无效)
post方法源码
java 复制代码
 public boolean post(Runnable action) {  
     //1  
     final AttachInfo attachInfo = mAttachInfo;  
     if (attachInfo != null) {  
         return attachInfo.mHandler.post(action);  
     }  
  
     //2
     getRunQueue().post(action);  
     return true;  
  }

主要分为1,2两部分

  1. 如果AttachInfo不为空则调用mHandler.post(action)方法,attachInfo赋值在dispatchAttachedToWindow方法中,该方法会在view执行绘制、测量的时候调用
java 复制代码
void dispatchAttachedToWindow(AttachInfo info, int visibility) {  
    //1、mAttachInfo赋值  
    mAttachInfo = info;  
  
    //2、 执行之前挂起的所有任务,这里的任务是通过 getRunQueue().post(action)挂起的任务, 也就是View.post()方法中当attachInfo为null时执行的那行代码
    if (mRunQueue != null) {  
        mRunQueue.executeActions(info.mHandler);  
        mRunQueue = null;  
    }  
  
    //3、回调View的onAttachedToWindow方法,该方法在onResume之后,View绘制之前执行  
    onAttachedToWindow();   
}  
  1. 如果attachInfo为空也就是当前执行View.post()方法时还没有绘制view,此时会执行getRunQueue().post(action)
java 复制代码
private HandlerActionQueue getRunQueue() {  
   if (mRunQueue == null) {  
        mRunQueue = new HandlerActionQueue();  
    }  
    return mRunQueue;  
}

HandlerActionQueue中主要是将Runnable任务保存到了队列中,等到dispatchAttachedToWindow的时机进行执行。也就是说即使我们调用View.post()方法的时候还没有执行view的绘制流程,View.post()方法也会将我们的Runnable任务挂起,等待合适的时机执行

总结

要点 说明
最佳实践 优先使用View.post()获取视图尺寸
执行时机 保证在measure/layout之后,首帧绘制前执行
线程安全 自动切换到主线程执行
注意事项 View必须已附加到Window,单独创建的View对象无法生效
相关推荐
Mr YiRan7 小时前
网络请求API监控与网络切换埋点
android·网络
美狐美颜sdk10 小时前
直播APP开发技术栈详解:视频美颜SDK、人脸识别与实时渲染
android·人工智能·音视频·美颜sdk·直播美颜sdk
奈斯先生Vector16 小时前
当模型版本不断变化,RelayRouter 能否帮助 AI 应用摆脱深度绑定
android·java·人工智能·开源·aigc
TimeFine16 小时前
让强模型做“总工”,让高性价比模型写代码
android
又见情义17 小时前
RK3568 Android 13 屏蔽 healthd 电池日志经验分享
android
古法安卓21 小时前
Android-Fork 机制详解
android·java·android studio
Android打工仔21 小时前
不要在 Data 层随意把 Cold Flow 转换成 Hot Flow
android·架构·kotlin
峥嵘life21 小时前
2026免费的 opencode 使用分享:Windows端 + 服务器CLI 实战总结
android·大数据·开发语言
杉氧1 天前
拒绝重复造轮子:我写了一个生产级的 Kotlin 协程与 Flow 工具库(CoroutineKit)
android·kotlin·workflow
恋猫de小郭1 天前
Flutter GSoC 2026 提案进度解读,补上 DevTools、FFI 和原生平台的关键缺口
android·前端·flutter