本节和《Android群英传》中的第3章Android控件架构与自定义控件详解有关系,建议先阅读该章的总结

第4章 View的工作原理

4.1 初始ViewRoot和DecorView

(1)ViewRoot对应ViewRootImpl类,它是连接WindowManagerDecorView的纽带,View的三大流程均通过ViewRoot来完成。
(2)ActivityThread中,Activity创建完成后,会将DecorView添加到Window中,同时创建ViewRootImpl对象,并建立两者的关联。
(3)View的绘制流程从ViewRoot的performTraversals方法开始,经过measurelayoutdraw三大流程。
(4)performMeasure方法中会调用measure方法,在measure方法中又会调用onMeasure方法,在onMeasure方法中会对所有的子元素进行measure过程,这个时候measure流程就从父容器传递到子元素了,这样就完成了一次measure过程,layout和draw的过程类似。 (书中175页画出详细的图示)
(5)measure过程决定了view的宽高,在几乎所有的情况下这个宽高都等同于view最终的宽高。layout过程决定了view的四个顶点的坐标和view实际的宽高,通过getWidthgetHeight方法可以得到最终的宽高。draw过程决定了view的显示。
(6)DecorView其实是一个FrameLayout,其中包含了一个竖直方向的LinearLayout,上面是标题栏,下面是内容栏(id为android.R.id.content)。

4.2 理解MeasureSpec
(1)MeasureSpecLayoutParams的对应关系
在view测量的时候,系统会将LayoutParams在父容器的约束下转换成对应的MeasureSpec,然后再根据这个MeasureSpec来确定View测量后的宽高。
MeasureSpec不是唯一由LayoutParams决定的,LayoutParams需要和父容器一起才能决定view的MeasureSpec,从而进一步确定view的宽高。对于DecorView,它的MeasureSpec由窗口的尺寸和其自身的LayoutParams来决定;对于普通view,它的MeasureSpec由父容器的MeasureSpec和自身的LayoutParams来共同决定。
(2)普通view的MeasureSpec的创建规则 (书中182页列出详细的表格)
当view采用固定宽高时,不管父容器的MeasureSpec是什么,view的MeasureSpec都是精确模式,并且大小是LayoutParams中的大小。
当view的宽高是match_parent时,如果父容器的模式是精确模式,那么view也是精确模式,并且大小是父容器的剩余空间;如果父容器是最大模式,那么view也是最大模式,并且大小是不会超过父容器的剩余空间。
当view的宽高是wrap_content时,不管父容器的模式是精确模式还是最大模式,view的模式总是最大模式,并且大小不超过父容器的剩余空间。

4.3 view的工作流程
(1)view的measure过程和Activity的生命周期方法不是同步执行的,因此无法保证Activity执行了onCreateonStartonResume时某个view已经测量完毕了。如果view还没有测量完毕,那么获得的宽高就都是0。下面是四种解决该问题的方法:
1.Activity/View # onWindowFocusChanged方法
onWindowFocusChanged方法表示view已经初始化完毕了,宽高已经准备好了,这个时候去获取宽高是没问题的。这个方法会被调用多次,当Activity继续执行或者暂停执行的时候,这个方法都会被调用。
2.view.post(runnable)
通过post将一个runnable投递到消息队列的尾部,然后等待Looper调用此runnable的时候,view也已经初始化好了。
3.ViewTreeObserver
使用ViewTreeObserver的众多回调方法可以完成这个功能,比如使用onGlobalLayoutListener接口,当view树的状态发生改变或者view树内部的view的可见性发生改变时,onGlobalLayout方法将被回调。伴随着view树的状态改变,这个方法也会被多次调用。
4.view.measure(int widthMeasureSpec, int heightMeasureSpec)
通过手动对view进行measure来得到view的宽高,这个要根据view的LayoutParams来处理:
match_parent:无法measure出具体的宽高;
wrap_content:如下measure,设置最大值

int widthMeasureSpec = MeasureSpec.makeMeasureSpec((1 << 30) - 1, MeasureSpec.AT_MOST);int heightMeasureSpec = MeasureSpec.makeMeasureSpec((1 << 30) - 1, MeasureSpec.AT_MOST);view.measure(widthMeasureSpec, heightMeasureSpec);

精确值:例如100px

int widthMeasureSpec = MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY);int heightMeasureSpec = MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY);view.measure(widthMeasureSpec, heightMeasureSpec);

(2)在view的默认实现中,view的测量宽高和最终宽高是相等的,只不过测量宽高形成于measure过程,而最终宽高形成于layout过程。
(3)draw过程大概有下面几步:
1.绘制背景:background.draw(canvas)
2.绘制自己:onDraw()
3.绘制children:dispatchDraw
4.绘制装饰:onDrawScrollBars

4.4 自定义view
(1)继承view重写onDraw方法需要自己支持wrap_content,并且padding也要自己处理。继承特定的View例如TextView不需要考虑。
(2)尽量不要在View中使用Handler,因为view内部本身已经提供了post系列的方法,完全可以替代Handler的作用。
(3)view中如果有线程或者动画,需要在onDetachedFromWindow方法中及时停止。
(4)处理好view的滑动冲突情况。

接下来是原书中的自定义view的示例,推荐阅读源码。

OK,本章结束,谢谢阅读。

转载于:https://www.cnblogs.com/dongweiq/p/5028991.html

《Android开发艺术探索》读书笔记 (4) 第4章 View的工作原理相关推荐

  1. Android开发艺术探索 读书笔记

    啥也不说了,@主席的<Android开发艺术探索>真是业界良心之作,不得不看!感谢主席,膜拜主席!主席主席,我要跟你生猴子!(>^ω^<) 读书笔记中若有任何问题请留言告知,谢 ...

  2. Android开发艺术探索读书笔记(一)

    首先向各位严重推荐主席这本书<Android开发艺术探索>. 再感谢主席邀请写这篇读书笔记 + 书评.书已经完整的翻完一遍了,但是还没有细致的品读并run代码,最近有时间正好系统的把整本书 ...

  3. Android 开发艺术探索 - 读书笔记目录

    仅作为读书笔记使用,建议阅读原书. 书中代码部分已和现版本不符,建议对比最新版本学习. 读了这本书,越发认识到和大佬们的差距.嗯,加油吧. 过去の自分が今仆の土台となる 第 1 章 - Activit ...

  4. Android开发艺术探索读书笔记

    前言 Android开发艺术(这本书真的是艺术,太崇拜刚哥了,值得每一个做Android开发刷十遍的书) 1,Activity生命周期和启动模式 典型情况下的生命周期分析 onCreate() onS ...

  5. Android开发艺术探索读书笔记(二)

    首先感谢大家支持,昨天第一篇写出来之后反响很好,主席本人也非常赞赏(捂脸-),再接再厉,推出第二篇.这篇的主要内容是对两章View的内容进行总结.不得不说,自定义View是很多开发者的痛点,一方面我们 ...

  6. Android开发艺术探索读书笔记(第5章 RemoteView)

    原理 RemoteView的作用是在其他进程中显示并更新view界面. 大量的IPC操作会影响效率,为了解决这个问题,系统并没有通过Binder去直接支持View的跨进程访问,而是提供了一个Actio ...

  7. 《android开发艺术探索》笔记之Bitmap的加载和Cache

    <Android开发艺术探索>笔记之Bitmap的加载和Cache<一> 我放暑假前,就在图书馆借了一本<Android开发艺术探索>,这也是我看到很多人推荐的.之 ...

  8. 《Android 开发艺术探索》笔记2--IPC机制

    <Android 开发艺术探索>笔记2--IPC机制 思维导图 Android IPC简介 Android中的多进程的模式 IPC基础概念 Serializable接口 Parcelabl ...

  9. 《Android开发艺术探索》笔记目录

    该笔记以<Android开发艺术探索>为基础,结合Android 9.0代码和官方文档,修正了原书中表述不明确和过时的部分,同时加入了大量的个人理解. 13章,14章,15章是总结性的章节 ...

最新文章

  1. 控制-动力学-拉格朗日建模
  2. 数据结构-排序(插入排序)
  3. 4.OD-调试示例1
  4. 【前端】前端笔试题 [1]
  5. headroom.js插件使用方法
  6. c语言 程序延时 校准,c语言实现系统时间校正工具代码分享
  7. Spring-Security 自定义Filter完成验证码校验
  8. (19)脚手架工具Yeoman
  9. 开源之旅之开源企业软件采购指南
  10. leetcode题库:1.两数之和
  11. [视频教程]用Unity3d开发跳一跳小游戏
  12. 08-10 性能瓶颈证据链
  13. ❤️Spring的静态、动态代理模式
  14. HashMap的实现原理看这篇就够了,图文源码详解,深入浅出简单易懂
  15. HTML DOM对象的属性和方法介绍(原生JS方法)
  16. webgate 重构 工作进度计划
  17. javaweb站点根目录和web应用根目录应用场景
  18. OSChina 周一乱弹 —— 带你装逼带你飞~
  19. 电源接头DC002的PCB封装
  20. DSPE-PEG7-NHS ester分子式:C63H1117N2O20P琥珀酰亚胺PEG连接剂

热门文章

  1. mysql大数据表无主键_oracle转mysql 表没有主键
  2. 棋盘覆盖-分治法(代码实现)
  3. 深入认识Tigase XMPP Server(上)
  4. python程序的name的作用是什么_python 中__name__ = '__main__' 的作用,到底干嘛的?
  5. linux内核oops错误码说明,调试 – 了解内核oops错误代码
  6. pythonwindows程序开发课程_Windows深入编程全集视频课程(七日成蝶)
  7. zabbix3 mysql_mysql分表-zabbix3.x
  8. 计算机辅助功能包括什么,CAD软件是什么?有什么功能?
  9. jar注册成服务器,Spring Boot项目生成jar包,并在windows服务器中注册成服务,开机启动(示例代码)...
  10. linux 内核 网卡驱动 移植,Linux内核移植步骤_添加DM9000网卡驱动(设备树).docx