5分钟告诉你,Activity的视图绘制流程(onMeasure、onLayout、onDraw的调用和参数解释)

本文针对有一定Android基础的开发者,详细剖析了Activity视图元素的绘制流程,包括DecorView、ViewRootImpl的作用,以及onMeasure、onLayout和onDraw的调用时机和参数来源。通过源码分析,阐述了从Activity的onResume到ViewRootImpl的初始化,再到View树的测量、布局和绘制的全过程。

本篇主要面对有一定Android基础的同学,但是Android初学者的话,也不要急。在网上可以看到很多文章,会告诉你onMeaure是什么?里面的参数是什么意思?会教你怎么获取MeaSpec的size和mode(Unspecified、Exactly、AtMost)。也会告诉你怎么重写 onLayout,怎么使用layout方法去布局子元素,怎么实现流式布局,自动换行。还有会告诉你重写onDraw(canvas),去玩canvas去绘图,然后你会了解到PathMeasure、Bitmap、Drawable等。

但是我们还是很懵逼,为啥重写这些方法之后就行了呢?ViewGroup的measure和View的measure有啥区别呢?为啥我们有这些困惑?其实是我们的学习路线有点问题。

最好的学习方式都是top-bottom,自顶向下的,你考虑下如果我直接告诉你,onMeasure就是测量函数,里面的Mespec参数就是要通过getMode方法取模式,你是不是很懵逼、很排斥。但是如果我告诉你其实整个Activity视图元素都是在一个窗口里面的(PhoneWindow),窗口有个根View(DecorView),它的展示过程有测量、布局、绘制3个操作(measure, layout, draw),他会遍历他下面所有的View和ViewGroup,ViewGroup又遍历ViewGroup。如果把DecorView看成树的根节点的话,绘制过程就是一个树的深度遍历过程。你想要操作View(控制大小,控制布局,控制样式),其实就是操作onMeasure、onLayout、onDraw。这样讲解是不是就能懂了呀 呀呀!!!


前言

在上篇5分钟告诉你,Activity的生命周期怎么触发的(onCreate onStart onResume onPause onStop onDestroy)(附测试代码)分析Android源码是怎么调用Activity的生命周期中,我们提到了ViewRootImpl的创建,然后通过它的performTraversal,分别执行了perfromMeasure、performLayout、performDraw,来进行遍历所有View树中View节点。

这篇我先提出几个问题,然后咱们带着问题来找答案。

  1. ViewRootImpl是什么,它是什么时候创建的?
  2. DecorView是什么?ViewRootImpl是怎样执行遍历View的过程的?
  3. onMeasure、onLayout、onDraw是什么时候调用的?他们的参数是谁给他们的?

篇幅比较长,通过几个问题查看源码来解读的,请耐心的看。想先大体了解一下的同学,可以直接滑到最后结论。

【转载请注明出处:5分钟告诉你,Activity的视图绘制流程(onMeasure、onLayout、onDraw的调用和参数解释) 优快云 王智博


正片

1.初识DecorView

上篇我们讲解Activity生命周期的时候讲解到,Activity的创建和onCreate的回调是在ActivityThread.performLauchActivity,Activity创建之后,调用attach方法

step1. activity.attach(appContext, this, getInstrumentation(), r.token,...)

activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);

我们进去

### Android 视图生命周期方法调用顺序 在 Android 开发中,理解视图(View)的生命周期对于优化应用性能调试非常重要。以下是 `onAttachedToWindow`、`onMeasure` `onDetachedFromWindow` 方法的具体调用顺序。 #### 1. `onAttachedToWindow` 当一个 View 或者其父容器被附加到窗口时会触发此方法。通常情况下,在 Activity 的 `onResume()` 后发生[^2]。这意味着此时 Window 已经准备好并准备绘制内容: ```java @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); Log.d("Lifecycle", "View attached to window"); } ``` #### 2. `onMeasure` 一旦 View 成功附着到了窗口上,并且布局参数已经设置完毕,则系统会对该组件及其子项进行测量操作来确定它们各自的尺寸大小。这一步骤紧接在 `onAttachedToWindow` 之后完成,但在实际显示之前还需要经过其他几个阶段如 `onLayout` `onDraw` 等[^3]。 ```java @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 自定义测量逻辑... setMeasuredDimension(width, height); } ``` #### 3. `onDetachedFromWindow` 当某个特定的 View 不再属于任何窗口的一部分时就会调用这个函数;它一般会在整个 Activity 销毁(`onDestroy`)过程结束以后被执行。需要注意的是,如果只是隐藏了一个界面而不是完全关闭的话,那么这里可能不会立即执行。 ```java @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); Log.d("Lifecycle", "View detached from window"); } ``` 综上所述,这三个方法按照如下顺序被调用:先是在 `onResume()` 完成后不久调用了 `onAttachedToWindow`,接着是 `onMeasure` 参与计算各部件所需空间,最后则是应用程序退出前一刻才会有机会遇到 `onDetachedFromWindow` 出现的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值