UI绘制流程,让无数安卓工程师无从下手?一篇文章就教你读懂!

前言

在android当中对于UI体系当中往往我们会在绘制UI的时候碰到各种各样的问题而不知道从何解决, 也有时需要开发更改自定义组件时,需要做自己的调整,或者是实现某个自定义特效时的思路不明确,想要达到去玩转UI的最为基础的部分,就是去全面的深入了解UI的绘制流程.所以接下来带大家去进行全面分析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

然后在下面我门会发现在做了一件事情,

当前这里竟然在加载布局文件,并且生成了一个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绘制过程我们就已经非常清楚了。

我们可以根据这种绘制的流程来操作自己的自定义组件。

BATJ、字节跳动面试专题,算法专题,高端技术专题,混合开发专题,java面试专题,Android,Java小知识,到性能优化.线程.View.OpenCV.NDK等已经上传到了的我的GitHub

大家点击我的GitHub地址:https://github.com/Meng997998/AndroidJX点下star一起学习

原文地址:https://blog.51cto.com/14606040/2465682

时间: 2024-08-29 10:57:27

UI绘制流程,让无数安卓工程师无从下手?一篇文章就教你读懂!的相关文章

BAT安卓工程师面试流程解析+还原最真实最完整的一线公司面试题

尊重原创,转载请写明原文出处:http://blog.csdn.net/sk719887916/article/details/47040931 (skay) 求职和我们每个人息息相关,而求职也有门道,好的发挥和技巧或许能以压倒性优势在面试中胜出,回或许我们技不如人,但是我们的综合能力如果良好的话,企业也愿意招这样的人,因此我将自己亲身经历的BAT和其他知名互联网的面试经验分享给大家,让有技术的人展现获得展现自我的平台,前几天在网上一搜,一系列的百度面试题,我特别兴奋,点击练链接一看,差点给吓尿

Android中View绘制流程以及invalidate()等相关方法分析

前言: 本文是我读<Android内核剖析>第13章----View工作原理总结而成的,在此膜拜下作者 .同时真挚地向渴望了解 Android 框架层的网友,推荐这本书,希望你们能够在Android开发里学到更多的知识 . 整个View树的绘图流程是在ViewRoot.java类的performTraversals()函数展开的,该函数做的执行过程可简单概况为 根据之前设置的状态,判断是否需要重新计算视图大小(measure).是否重新需要安置视图的位置(layout).以及是否需要重绘 (d

Android中View绘制流程分析

创建Window 在Activity的attach方法中通过调用PolicyManager.makeNewWindo创建Window,将一个View add到WindowManager时,WindowManagerImpl创建一个ViewRoot来管理该窗口的根View.并通过ViewRoot.setView方法把该View传给ViewRoot. final void attach(Context context, ActivityThread aThread, Instrumentation

android源码解析(十八)--&gt;Activity布局绘制流程

这篇文章是承接上一篇文章(Android布局加载流程:http://blog.csdn.net/qq_23547831/article/details/51284556)来写的,大家都知道Activity在Android体系中扮演者一个界面展示的角色,通过上一篇文章的分析,我们知道Activity是通过Window来控制界面的展示的,一个Window对象就是一个窗口对象,而每个Activity中都有一个相应的Window对象,所以说一个Activity对象也就可以说是一个窗口对象,而Window

Android视图View绘制流程与源码分析(全)

来源:[工匠若水 http://blog.csdn.net/yanbober] 1 背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原理,记不记得最终分析结果就是下面的关系: 看见没有,如上图中id为content的内容就是整个View树的结构,所以对每个具体View对象的操作,其实就是个递归的实现. 前面<Android触摸屏事件派发机制详解与源码分析一(

Chromium的UI绘制初探

转载请注明出处:http://www.cnblogs.com/fangkm/p/3943896.html 常见的UI库的绘制逻辑 任何一个成熟的界面框架都有一个相当复杂的结构,消息循环的处理.控件的布局与绘制.焦点的管理以及资源的存取等等,Chromium里的界面框架也不例外,尤其采用的MVC设计方式更是增添了代码结构的复杂度.这里并不打算讨论Chromium的界面框架,本文感兴趣的只是Chromium的UI绘制部分,确切地说应该是引入Aura架构之后控件渲染的硬件加速支持. 在常见的Direc

产品经理业务流程图的绘制流程分享

产品经理业务流程图的绘制流程分享 2012/06/28 阅读(72102) 评论(12) 收藏(159) 来人人都是产品经理[起点学院],BAT实战派产品总监手把手系统带你学产品.学运营.点此查看详情 图1:用即时贴与白板做的简单流程图 前言:近来一段时间,忙于整理业务流程图,期间,关于流程图的绘制方法和工具也与内部团队和外部做了心得交流,恰好,个人生活也牵涉在买房,婚礼,户口迁移等流程中.不知不觉,伴随着实践与反思,个人所得的系统知识趋于完整,今儿天气极好,坐在飘窗一隅,听着间或几声鸟鸣歌唱,

深入理解 Android 之 View 的绘制流程

概述 本篇文章会从源码(基于Android 6.0)角度分析Android中View的绘制流程,侧重于对整体流程的分析,对一些难以理解的点加以重点阐述,目的是把View绘制的整个流程把握好,而对于特定实现细节则可以日后再对相应源码进行研读.在进行实际的分析之前,我们先来看下面这张图: 我们来对上图做出简单解释:DecorView是一个应用窗口的根容器,它本质上是一个FrameLayout.DecorView有唯一一个子View,它是一个垂直LinearLayout,包含两个子元素,一个是Titl

Android学习笔记&mdash;&mdash;OpenGL ES的基本用法、绘制流程与着色器编译

首先声明下,本文为笔者学习<OpenGL ES应用开发实践指南(Android卷)>的笔记,涉及的代码均出自原书,如有需要,请到原书指定源码地址下载. 在Android.iOS等移动平台上,开发者可以使用跨平台应用编程接口创建二维或者三维图形,或进行图像处理和计算机视觉应用,结合两者将能构建丰富有趣的交互体验.前者称为OpenGL,后者称为OpenCV,不过本文主要介绍前者,OpenCV在后续文章中涉及.OpenGL应用于桌面系统的历史已经很长了,但考虑到移动平台的特点(计算能力.性能等),将