android view绘制过程,浅谈Android View绘制流程

前言

日常开发中,获取xml文件中控件宽度和高度的需要,是我们经常遇到的。但是在Activity的生命周期中获取控件的宽高,onCreate()中获取拿到的值往往是0,在onResume中尝试获取,依旧失败,有一定开发经验的小伙伴都知道,要想得到控件的宽高数据,必须是UI布局执行Measure(),onlayout()之后(具体原因笔者也暂时说不清楚,有待后续补充。。。。。。),才会获取到值,综上所述 Activity 生命周期onResume()执行之前布局文件是没有进行绘制的。由此笔者想深入了解一下Android绘制流程,这就是这篇文件的由来。

先解决上面提到的问题,Activity生命周期过程中,如何获取控件的宽高???

可以在onWindowFocusChanged(boolean hasFocus){}中获取控件的宽高,

另外Activity生命周期方法和View绘制的流程大致如下:

oncreate()→onResume()→onMeasure()→onLayout()→onWidnowFocusChanged()→.....→onDraw()...

参考文档:Android中的onWindowFocusChanged()方法详解

正文

View和Activity相关联的,分析View的绘制过程,往往离不开Activity的分析,所以我们还是先从Activivty的生命周期说起。

ActivityManagerService(简称AMS)是Android 上层系统中比较核心的服务之一,负责系统四大组件的启动,切换,调度以及应用程序的管理和调度等工作。查看源码可知,ActivityThread的main方法是应用程序的入口,main()方法中做一些初始化的工作,包括连接AMS。

另外ActivityThread负责管理Activity,应用所有的Activity都存在ActivityThread中的mActivities集合中。

ActivityThread需要借助ApplicationThread响应AMS的号召,Main()方法中调用attch()方法就是让ApplicationThread和AMS建立联系。

当Activity启动时会先调用到scheduleLaunchActivity()方法,由Handler发送通知消息后执行handleLaunchActivity()->performLaunchActivity()->callActivityOnCreate()->Activity.onCreate()。

onResume()时也一样,当Activity的状态发生改变,经过层层调用执行到handleResumeActivity()方法,在方法中先调用Activity.onResume()方法,再执行WindowManager的addView()方法将Activity的根View(DecorView)添加上去,进而开始绘制流程。这就解释了为什么初次在onResume()方法中获取不到View的宽高。

WindowManagerImpl是WindowManager的实现类,它的addView()方法调用了WindowManagerGlobal的addView()方法。

addView()方法中先创建ViewRootImpl对象,随后执行setView()方法将其和DecorView绑定起来,绘制流程也将由ViewRootImpl()来执行。setView()方法中会执行requestLayout()方法。

requestLayout()方法走下去会异步执行performTraversals()方法,View的三大流程都是在该方法中执行的。到这儿我们算是明白View的绘制流程是从哪儿开始的,这个流程下来,读者看着估计蒙了一比,我写的也比较蒙,尝试着梳理归纳一下吧:

1. ActivityThread.main(基本初始化,attch将ApplocationThread和AMS建立联系)程序入口。

2. 生命周期onCreate()调用过程:Activtiy启动scheduleLaunchActivity()》

handleLaunchActivity()》PerformLaunchActivity()》callActivityCreate()》Activity.onCreate();

3. Activity.onResume()方法执行之后,WindowManager的实现类WindowManagerImpl.addView()中在

调用WindowManagerGlobal.addView()方法,

将根View(DecorView)添加进去。

4. WindowManagerGlobal.addView()方法中,创建ViewRootImpl对象后,执行setView将

ViewRootImpl对象和DecorView绑定,并执行requestLayout方法,该方法会异步执行

performTraversals()方法,View三大绘制流程(measure、layout、draw)就在这个方法中执行

怎么说呢,不看源码,单独看笔者写的这篇文档,看的肯定云里雾里,当看过源码或者源码分析相关博客之后,再回来看这篇文章,算是脱离源码,对这整个流程的一个简单总结,由于笔者能力有限,精力有限,只能尽自己最大的努力,总结自己看到的。下面是笔者对这一部分画的一个简单流程图,更形象些,更容易记住了解整个流程。

9ea60bb3025bc1cc387f2c18acd5971c.png

View的绘制流程.png

总结

这篇文章算是笔者浏览View绘制相关博客的一些总结,写的比较乱,估计也就是自己能够看懂,能够帮助的其他人最好,只求不要又误导其他的人的地方。另外,笔者想说的是:有些东西看懂了,不一定能写出来,能写出来不一定会用,看过之后,写出来,只为了加深自己的印象,方便以后查看,虽然写的不够好,但是还是要坚持,不坚持写,永远不会有好的结果,坚持下去,才会有有可能开花结果,毕竟越努力越幸福

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值