Android的显示过程可以简单的概括为:Android应用程序把经过测量、布局、绘制后的sruface缓存数据,通过SurfaceFlinger把数据渲染到显示屏幕上,通过Android的刷新机制来刷新数据。也就是说应用层负责绘制,系统层负责渲染,通过进程间通信机制把应用层需要绘制的数据传递到系统层服务,系统层服务通过刷新机制把数据更新到屏幕。
1.应用层测量布局绘制流程:
应用层由很多不同层次的基本元素——view,整体是一个树形结构,有不同的嵌套,存在着父子关系,子View在父View中,这些View都经过一个相同的流程最终显示到屏幕上,这也意味着要显示所有的数据,就要对其中所有的View都进行一次绘制工作,并针对每个View的绘制工作都是一个递归过程。
应用层View的绘制要经过测量、布局、绘制过程,并且每个View都要执行一次这样的操作,并且View的绘制流程是一个递归过程,即先从最底层的子View开始绘制,那么View的层级越深,View元素越多,绘制越耗时。
android在测量的过程中,需要用到一个帮助类MeasureSpec,它封装了父布局传递给子布局的布局要求。一个MeasureSpec有大小和模式组成,它有三种模式:
UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;
EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;
AT_MOST(至多),子元素至多达到指定大小的值。
它常用的三个函数:
//根据提供的测量值(格式)提取模式(上述三个模式之一)
static int getMode(int measureSpec){
return (measureSpec & MODE_MASK);
}
//根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)
static int getSize(int measureSpec){
return (measureSpec & ~MODE_MASK);
}
//根据提供的大小值和模式创建一个测量值(格式)
static int makeMeasureSpec(int size,int mode){
return size + mode;
}
目前android绘制的方式有两种,第一种是软件绘制(CPU)和硬件加速(GPU),很显然,硬件加速在UI的显示和绘制的效率远远高于CPU绘制,但是硬件加速也有其缺陷:
1).耗电,GPU的功耗比CPU高
2).兼容问题,某些接口和函数不支持硬件加速
3).内存大,使用openGL的接口至少需要8MB内存
2.系统层绘制流程
真正把需要显示的数据渲染到屏幕上,是通过系统级进程中的SurfaceFlinger服务来实现的,SurfaceFlinger的主要工作有:
1).响应客户端事件,创建Layer与客户端的Surface建立连接。
2).接受客户端的数据及属性,修改Layer属性,如尺寸、颜色、透明度等。
3).将新建的Layer数据刷新到屏幕上。
4).维持Layer的序列,并对Layer输出做出裁剪计算。
系统层和应用层之间的通信是跨进程的,所以需要一个跨进程的通信机制来实现数据传输。在Android的显示系统,使用了Android的匿名共享内存:SharedClient。每一个应用和SurfaceFlinger之间都会创建一个SharedClient,一个SharedClient对应一个Android应用程序。在每个SharedClient中,最对可以创建31个SharedBufferStack,每一个surface对应一个SharedBufferStack,也就是一个window。
最后总结起来显示流程分为三个模块:应用层绘制到缓存区,SurfaceFlinger把缓存区数据渲染到屏幕,由于是两个不同的进程,所以使用Android的匿名共享内存SharedClient缓存需要显示的数据来达到目的。
网友评论