震惊!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对象无法生效
相关推荐
松仔log12 小时前
Java中级——组合和继承
android·java·开发语言
我命由我1234516 小时前
Jetpack Compose - MaterialExpressiveTheme 与 MaterialTheme、ColorScheme
android·java·开发语言·java-ee·kotlin·android jetpack·android runtime
lilian23316 小时前
Harmony os 技术实战|拼豆制图06:收藏 ID、生成记录与重启恢复怎么不打架
android·java·数据库·harmonyos
2601_9557596217 小时前
ClaudeAPI成本中心与业务标签设计指南
android·java·数据库
余衫马17 小时前
2026最新版!Android Studio 极速安装与配置指南
android·ide·android studio
AFinalStone17 小时前
Android 7系统异常问题排查(五)Framework层(下)—System Server崩溃
android·tombstone·系统异常
AFinalStone17 小时前
Android 7系统异常问题排查(八)系统追踪—Trace机制与性能诊断
android·系统异常
极客猴子21 小时前
Android录音转写频繁卡顿?多款APP长时间会议场景稳定性实测
android·人工智能·智能手机·飞书
Kapaseker21 小时前
Boolean 变量到底该怎么命名?
android·kotlin
AFinalStone21 小时前
Android 7系统异常问题排查(六)应用异常(上)—ANR机制全解
android·系统异常