• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

31张图总结一鼓作气学会UI绘制流程详解整体启动流程

android 搞代码 3年前 (2022-03-01) 22次浏览 已收录 0个评论
文章目录[隐藏]

前言

在android当中对于UI体系当中往往咱们会在绘制UI的时候碰到各种各样的问题而不晓得从何解决, 也有时须要开发更改自定义组件时,须要做本人的调整,或者是实现某个自定义特效时的思路不明确,想要达到去玩转UI的最为根底的局部,就是去全面的深刻理解UI的绘制流程.所以接下来带大家去进行全面剖析UI整体的绘制体系.

  • 公众号:小新聊Android
  • github地址

UI整体的绘制体系思路及纳闷

思路

android程序启动—>Activity加载并实现生命周期—>setContentView—>图形绘制

纳闷:

1.Android程序是如何启动,Activity生命周期如何调用?

2.在Activity onCreate当中咱们的setContentView是如何将UI文件加载?

3.UI是如何绘制的?

答案:

1.Android程序流程

家喻户晓,咱们的java程序想要开启须要依赖于main办法,也就是咱们的程序入口(主线程)进入,然而在咱们日常开发android程序的过程当中咱们并没有发现main办法的存在,那么android当中的是如何开始运行的?

相熟的敌人们可能都晓得在android当中存在一个叫做ActivityThread的类,这个类代表的是android当中的主线程,而在这个类当中咱们看到了比拟相熟的main办法,那么当初是否能够认为咱们的android在关上app时是首先调用的是以后这个类的main,也就是此处为咱们的启动点

在此处能够看到Activity调用了一个attach()办法

在这里咱们可能首先要思考的是getService拿进去的是什么? 进去之后,咱们会发现

在这个当中,外面调用了的零碎的ActivityManagerService这个服务,并且给出了一个Binder接口

那么在这里,咱们能够联想到,在android当中的binder通信机制,那么实际上咱们的ActivityManager是有零碎服务所调用治理,并且通过在binder接口当中进行调用,这也是为什么咱们讲Activity是跨过程拜访的起因

那么明确了这个时候可能失去ActivityManager之后,咱们接着回到attach当中持续看上来, 这个时候会发现,咱们调用了一个attachApplication办法(见图2)这个办法又是干嘛的? attachApplication在这里的作用其实实际上是ActivityThread通过attach获取到,而后将applciationThread将其关联,把activity相干信息存储在applciationThread外面,apllicationThread的类为activity的各种状态做了绝对应的筹备工作

这个时候咱们须要关注,ApplicationThread当中做了什么? 当咱们关上ApplicationThread中咱们会看到一堆的schedle办法,这些办法的名称其实就能够给咱们表明,代表的是在执行Activity的某种状态时调用的打算执行办法

这时咱们会看到一个scheduleLaunchActivity办法,示意打算加载时调用的。这里我门发现了一个很有意思的事件

这个下面咱们会看到一个ActivityClientRecord对象,这个对象其实实际上就是咱们的Activity,而且仿佛每一个办法还干了一件让咱们十分相熟的一件事, 进行了一次sendMessage()将以后创立的Activity发送了进来

当走到这里咱们会发现最终咱们调用的是Handler的音讯通信机制,也就是说,在这里咱们能够总结一下,当Activity状态扭转时,都会有对应的一个音讯发送进来。而接管这里,我能发现通过发送时不同的状态,这边调用了不同的handlerXXXActivity办法

在这里,我门貌似发现了Activity的生命周期的调用痕迹,那么其实到此为止,我门能够得出一个论断,Application运行的过程当中,对于Activity的操作,状态转变,其实实际上是通过Handler音讯机制来实现的,Application当中只管去发, 由音讯机制负责调用,因为在main办法当中我门的Looper轮训器是始终在进行轮训的,而当咱们在加载Activity的时候,当中调用了一个performLaunchActivity()办法,在这个两头我发现了咱们onCreate的调用痕迹

也就是说,到目前为止咱们可能明确,整个Application加载Activity的整套流程是怎么回事? 那么接下来咱们须要关注的是,在onCreate当中咱们所写的setContentView到底干了什么

2.setContentView

在onCreate当中咱们往往会应用setContentView去进行设置咱们本人的布局文件或者view,那么在这当中他到底是怎么做的?通过观察源码,这个时候通过一系列线索我找到了最终的地位PhoneWindow类

这个时候咱们会看到他做了两个事件,一个是installDecor,另一个是inflate,这两个后一个不难猜出他是在进行布局文件的解析, 后面的咱们认为她是在初始化某个货色

进来之后发现他初始化了两个货色,一个叫做mDecor,一个叫做mContentParent

咱们看到了mDecor是一个DecorView,mContentParent是一个ViewGroup

透过正文的翻译,其实咱们就能很明确晓得这两个是用来干嘛的

// This is the view in which the window contents are placed. It is either(这是窗口内容搁置的视图)

// mDecor itself, or a child of mDecor where the contents go.(它要么是mDecor自身,要么是mDecor的子类的内容。)

//This is the top-level view of the window, containing the window decor.(**这是在窗口当中的顶层View,蕴含窗口的decor**)

一个代表的是顶层view,一个用来装他上面的视图内容。 在接着往下看的时候,我门发现generateLayout办法当中,发现了在此处进行了大量的requestFeature的调用,也就是说,咱们的requestFeature设置其实是在setContentView办法当中就开始了, 这也是为什么咱们本人要去getWindow.requestFeature时必须在setContent之前的起因

而后在上面咱们会发现在做了一件事件

以后这里居然在加载布局文件,并且生成了一个view, 然而如同貌似不是我门本人的。所以咱们须要去探寻他到底加载了一个什么东东?

这是我找到了一个比拟有意思的组件,在这个下面我看到了一句这样的正文

//This is an optimized layout for a screen, with the minimum set of features enabled.

这是一个屏幕的优化布局,具备最小的特色集启用。通过正文和一些材料剖析, 失去了一个比拟坑的后果。

这是DecorView默认的一个渲染,而后我门本人的布局都是渲染到她的FrameLayout上的。那么在这里我门当初可能明确,installDector其实实际上是在初始化两个视图容器,而后加载零碎的R资源及特色,产生了一个根本布局

那么接着回到之前我门关注的另外一个办法mLayoutInflater.inflate(layoutResID, mContentParent);这个办法就比拟好了解了。

这这段正文下面我门就能够失去一个信息

//Inflate a new view hierarchy from the specified xml resource.(从指定的视图当中获取试图的层次结构,意思就是,当初在加载本人的资源)

而具体流程就不贴代码了给各位上一张图

那么在这里我门就可能明确,setContentView其实做了两件比拟外围的事件,就是加载环境配置,和本人的布局,那么接下来我门须要思考的事件就是,他到底怎么画到界面上的

3.UI是如何绘制的?

通过后面两个章节,我门理解到,程序对于activity生命周期的调用,以及咱们的视图资源的由来。这是我门须要找到的是我门的绘制终点在哪?

在ActivityThread启动时, 我发现在加载handleLaunchActivity办法调用performLaunchActivity办法之后又调用了一个handleResumeActivity在这里我发现了绘制流程的开始

通过后面的流程我门晓得,onCreate之行实现之后,所有资源交给WindowManager保存。在这里将咱们的VIew交给了WindowManager,此处调用了addView

进入addView之后咱们发现了一段这样的代码,他将视图,和参数还有我门的一个ViewRoot对象都用了容器去装在了起来,那么在此处我门能够得出,是将所有的相干对象保存起来:

  • mViews保留的是View对象,DecorView
  • mRoots保留和顶层View关联的ViewRootImpl对象
  • mParams保留的是创立顶层View的layout参数。
  • 而WindowManagerGlobal类也负责和WMS通信

而在此时,有一句要害代码root.setView,这里是将咱们的参数,和视图同时交给了ViewRoot,那么这个时候咱们来看下ViewRoot当中的setView干了什么

终于在这里让我发现了让我明确的一步

在这里我门会看到view.assignParent的设置是this, 那么也就是说在view当中parent其实实际上是ViewRoot

那么在setContentView当中调用了一个setLayoutParams()是调用的ViewRoot的,而在ViewRoot当中发现了setLayoutParams和preformLayout对requestLayout办法的调用

在requestLayout当中发现了对scheduleTraversals办法的调用而scheduleTraversals当中调用了doTraversal的拜访,最终拜访到了performTraversals(),而在这个外面我发现了整体的绘制流程的调以后外面顺次是用了

UI绘制先回去测量布局,而后在进行布局的摆放,当所有的布局测量摆放结束之后,进行绘制。至此整体UI绘制过程咱们就曾经十分分明了,咱们能够依据这种绘制的流程来操作本人的自定义组件。

看完三件事❤️


如果你感觉这篇内容对你还蛮有帮忙,我想邀请你帮我三个小忙: 点赞反对,有你们的 『点赞和评论』,才是我发明的能源。


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:31张图总结一鼓作气学会UI绘制流程详解整体启动流程

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址