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

前言

在android当中对于UI体系当中每每咱们会在绘制UI的时候碰到各类各样的问题而不知道从何解决, 也有时须要开发更改自定义组件时,须要作本身的调整,或者是实现某个自定义特效时的思路不明确,想要达到去玩转UI的最为基础的部分,就是去全面的深刻了解UI的绘制流程.因此接下来带你们去进行全面分析UI总体的绘制体系.java

思路:android程序启动-→Activity加载并完成生命周期-→setContentView-→图形绘制android

疑惑:

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

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

3.UI是如何绘制的?

答案:面试

1.Android程序流程

众所周知,咱们的java程序想要开启须要依赖于main方法,也就是咱们的程序入口(主线程)进入,可是在咱们平常开发android程序的过程中咱们并无发现main方法的存在,那么android当中的是如何开始运行的?算法

熟悉的朋友们可能都知道在android当中存在一个叫作ActivityThread的类,这个类表明的是android当中的主线程,而在这个类当中咱们看到了比较熟悉的main方法,那么如今是否能够认为咱们的android在打开app时是首先调用的是当前这个类的main,也就是此处为咱们的启动点性能优化

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

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

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

在这里咱们可能首先要考虑的是getService拿出来的是什么?ide

进去以后,咱们会发现oop

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

在这个当中,里面调用了的系统的ActivityManagerService这个服务,而且给出了一个Binder接口

那么在这里,咱们能够联想到,在android当中的binder通讯机制,那么实际上咱们的ActivityManager是有系统服务所调用管理,而且经过在binder接口当中进行调用,这也是为何咱们讲Activity是跨进程访问的缘由

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

那么明白了这个时候可以获得ActivityManager以后,咱们接着回到attach当中继续看下去, 这个时候会发现,咱们调用了一个attachApplication方法(见图2)这个方法又是干吗的?attachApplication在这里的做用其实其实是ActivityThread经过attach获取到,而后将applciationThread将其关联,把activity相关信息存储在applciationThread里面,apllicationThread的类为activity的各类状态作了相对应的准备工做

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

这个时候咱们须要关注,ApplicationThread当中作了什么?

当咱们打开ApplicationThread中咱们会看到一堆的schedle方法,这些方法的名称其实就能够给咱们代表,表明的是在执行Activity的某种状态时调用的计划执行方法

这时咱们会看到一个scheduleLaunchActivity方法,表示计划加载时调用的

这里我发现了一个颇有意思的事情

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

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

这个上面咱们会看到一个ActivityClientRecord对象,这个对象其实实际上就是咱们的Activity

并且彷佛每个方法还干了一件让咱们很是熟悉的一件事, 进行了一次sendMessage()将当前建立的Activity发送了出去

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

当走到这里咱们会发现最终咱们调用的是Handler的消息通讯机制,也就是说,在这里咱们能够总结一下,

当Activity状态改变时,都会有对应的一个消息发送出去

而接收这里,我能发现经过发送时不一样的状态,这边调用了不一样的handlerXXXActivity方法

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

在这里,我门貌似发现了Activity的生命周期的调用痕迹,那么其实到此为止,我门能够得出一个结论,

Application运行的过程中,对于Activity的操做,状态转变,其实其实是经过Handler消息机制来完成的,

Application当中只管去发, 由消息机制负责调用,由于在main方法当中我门的Looper轮训器是一直在进行轮训的

而当咱们在加载Activity的时候,当中调用了一个performLaunchActivity()方法,在这个中间我发现了咱们onCreate的调用痕迹

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

也就是说,到目前为止咱们可以明白,整个Application加载Activity的整套流程是怎么回事

那么接下来咱们须要关注的是,在onCreate当中咱们所写的setContentView到底干了什么

2.setContentView

在onCreate当中咱们每每会使用setContentView去进行设置咱们本身的布局文件或者view,那么在这当中他究竟是怎么作的?经过观察源码,这个时候经过一系列线索我找到了最终的位置PhoneWindow类

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

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

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

进来以后发现他初始化了两个东西,一个叫作mDecor,一个叫作mContentParent

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

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

咱们看到了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

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

而后在下面我门会发如今作了一件事情,

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

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

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

当前这里居然在加载布局文件,而且生成了一个view, 可是好像貌似不是我门本身的

因此咱们须要去探寻他到底加载了一个什么东东?

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

这是我找到了一个比较有意思的组件,

在这个上面我看到了一句这样的注释

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

enabled.

这是一个屏幕的优化布局,具备最小的特征集启用。

经过注释和一些资料分析, 获得了一个比较坑的结果。

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

这是DecorView默认的一个渲染,而后我门本身的布局都是渲染到她的FrameLayout上的

那么在这里我门如今可以明白,installDector其实其实是在初始化两个视图容器,而后加载系统的R资源及特征,产生了一个基本布局

那么接着回到以前我门关注的另一个方法mLayoutInflater.inflate(layoutResID, mContentParent);

这个方法就比较好理解了,

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

这这段注释上面我门就能够获得一个信息

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

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

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

那么在这里我门就可以明白,setContentView其实作了两件比较核心的事情,就是加载环境配置,和本身的布局,那么接下来我门须要考虑的事情就是,他到底怎么画到界面上的

3.UI是如何绘制的?

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

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

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

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

经过前面的流程我门知道,onCreate之行完成以后,全部资源交给WindowManager保管

在这里,将咱们的VIew交给了WindowManager,此处调用了addView

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

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

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

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

mViews保存的是View对象,DecorView

mRoots保存和顶层View关联的ViewRootImpl对象

mParams保存的是建立顶层View的layout参数。

而WindowManagerGlobal类也负责和WMS通讯

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

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

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

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

那么在setContentView当中调用了一个setLayoutParams()是调用的ViewRoot的

而在ViewRoot当中发现了setLayoutParams和preformLayout对requestLayout方法的调用

在requestLayout当中发现了对scheduleTraversals方法的调用而scheduleTraversals当中调用了doTraversal的访问,最终访问到了performTraversals(),而在这个里面,我发现了总体的绘制流程的调用

当前里面依次是用了

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

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

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

UI绘制先回去测量布局,而后在进行布局的摆放,当全部的布局测量摆放完毕以后,进行绘制。

至此总体UI绘制过程咱们就已经很是清楚了。

咱们能够根据这种绘制的流程来操做本身的自定义组件。

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

你们点击个人GitHub地址:https://github.com/Meng997998/AndroidJX点下star一块儿学习

相关文章
相关标签/搜索