Android 绘制知识点总结
Android绘制流程
-
绘制前世今生
我们都知道,当一个
Activity调用setContenView之后,我们就可以看到我们的内容被展示出来,那么到底是谁,将我们的页面内容,转变成屏幕显示的像素数据呢,我们从来一步步分析
-
DecorView是我们应用窗口的一个根容器,SetContentView,其实就是将内容防止到DecorView的子元素id为ContentView的容器中 -
Window窗口,每一个窗口有一个和它关联的Surface,窗口的Surface由WMS分配,画在表面上的内容并不会马上显示在屏幕上,绘制完成之后,SurfaceFlinger将多块Surface按照顺序(Z-order)进行混合,输出到FrameBuff,显示到界面SurfaceView就是有一个单独Surface -
Window具体实现为PhoneWindow,和Activity唯一对应,PhoneWindow中持有DecorView,Activity.setContentView的操作就是通过PhoneWindow来完成Activity,Window,View的三者关系,Activity工匠,Window窗户,View窗花 -
ViewRoot,实现类ViewRootImple,会在ActivityThread.handleResumeActivity()和DecorView进行关联,而后会调用requestLayout发起绘制 -
绘制的起点,
ViewRootImpl.requestLayout ->scheduleTraversals() -> performTraversals()-
measure-> 计算出每个控件需要占据的尺寸-
MeasureSpec,32整数,SpecMode高2位+SpecSize剩余30位,- 测量模式
-
EXACTLY精准模式,指定了具体的尺寸,如12dp,或者是match_parent -
AT_MOST,最大模式,不得超过SpecSize -
UNSPECIFIED,未定义,不做限制,类似ListView这种系统内部控件
-
- 测量模式
-
-
layout->计算出每个控件的绘制位置 -
draw-> 每个空间的具体绘制内容
-
-
绘制核心
SurfaceFlinger-
无论是
OpenGL ES还是Canvas,获取MediaPlayer等生产者产生的图像数据都会输出到Surface, -
Surface也是作为SurfaceFlinger的生产者,将GraphicBuffer通过IPC传到SurfaceFlinger, -
最终
SurfaceFlinger根据WMS提供的窗口信息,合成所有的Layer(
Layer和Surface相关联,Surface是Layer的屏幕内存的直接表现)
- 图形绘制,不同的方式,都是输出到
Surface-
Canvas-
Sika软件绘制 -
hwui硬件加速绘制
-
OpenGL ES
-
-
BufferQueue,在之前的生产者-消费者模式中,所有的数据传输都是通过BufferQueue-
Canvas/OpenGLES请求一块空闲的缓存区填充图像数据dequeueBuffer(),然后将数据返回给队列:queueBuffer() -
SurfaceFlinger合成所有图层数据,放到输出缓存区 -
Display显示控制器 获取合成结果acquireBuffer(),使用完毕,则返回给队列:releaseBuffer()
-
-
-
双缓冲
CPU计算好显示内容之后,GPU负责渲染到FrameBuffer帧缓冲,然后按照VSync信用从帧缓冲中取出数据显示到屏幕上,如果只有一块缓冲区,那么数据的更新可能就是表现为逐行的刷新,为了刷新是整帧的,需要双缓冲,刷新时进行直接替换
Android硬件加速
在
Android中,硬件加速,就是将View的绘制工作交给GPU来完成,Android4.0以后,硬件加速都是默认开启的
Android硬件加速踩坑
-
一些
Android 4.0的低端机型,出现花屏,黑色像素,错位等现象,错误日志OpenGLRender:0x510-
针对一些自定义的复杂的
View,可能会存在渲染异常,出现这种情况,可以优先考虑关闭硬件加速-
Application级别关闭,慎用,这可能会让你整个应用的渲染性能下降<application android:hardwareAccelerated="false"> -
Activity级别关闭,悠着点,影响也不小<activity android:hardwareAccelerated="false"> -
Window级别,悠着点,也是和Activity类似getWindow().setFlags( WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); -
View级别,这个比较推荐!!view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);//指定为软件渲染 //也可以在布局文件xml中 android:layerType="software"
-
-
-
针对一些绘制相关的操作,也有一些
api是在特定版本后才开始支持硬件加速的-
Api支持版本 canvas.clipRegion()18 canvas.clipPath()18
-









网友评论