
与屏幕刷新相关的有很多,比如刷新流程,屏幕缓存,周期刷新,vsync信号,SurfaceFlinger。
接下来就一个个讨论具体的内容,并根据具体的内容,提出一些问题,做简单的解答
首先应用会向系统服务申请buffer,然后系统服务返回buffer,应用绘制后提交buffer给系统服务,系统服务再将buffer写入到屏幕缓冲区中,屏幕会以一定的帧率去刷新,从buffer中读取图像数据显示出来,buffer中没有新的图像数据,那么屏幕就会用老的数据,这样屏幕看起来就没有变化。
图像缓存不止有一个,因为假如只有一个缓存,系统服务向缓存写入数据,屏幕又读取缓存,这样屏幕就会一下子显示第一帧,一下子显示第二帧。可以申请两个缓存,如果要显示下一个缓存,可以进行缓存交换
屏幕周期刷新,根据vsync信号,每次根据信号,收到信号从缓存区中获取图像绘制,vsync信号是脉冲信号。
这里谈到到周期刷新,我们在进行view绘制的时候,会调用requestLayout进行重走一下measure,Layout,onDraw,那么此时调用10次requestLayout,会进行10次重绘吗
答案是当然不会,因为如果调用10次requestLayout,那么在下次vsync信号来的时候并不会触发10次ui重绘,在vsync周期中,只会触发一次界面重绘。
那绘制原理是什么呢,下面来具体讨论一下绘制原理
首先应用层的view调用requestLayout要进行重绘,其实通过callback新建一个runnable对象放入choreographer队列中,并没有马上处理这个消息,它首先向SurfaceFlinger请求下一个vsync信号,调用的就是requestNextVsync函数,然后SurfaceFlinger就会在下一个vsync信号来的时候,通过postSyncEvent向choreographe发送一个通知,choreographe收到通知,就会处理消息队列中的消息,调用performTraversal进行重绘
屏幕刷新流程,屏幕图像缓存,周期性刷新都讨论过了,还剩下vsync信号与SurfaceFlinger,剩下的在下面讨论,这时候针对之前的屏幕刷新机制,在来讨论几个问题
耗时操作,耽误view绘制
刷新屏幕指的是vsync信号的屏幕,但是不是每次vsync都去绘制,需要应用发起重绘,向SurfaceFlinger请求vsync信号,这样在下一次vsync信号来的时候,才会进行绘制
屏幕并不会立即刷新,需要等到下次vsync信号来的时候才会进行刷新
如果界面没有进行重绘,并不会收到vsync信号进行重绘,但是屏幕还会每隔16ms进行重绘,不过用的数据是旧图像数据,看起来屏幕没有变化
不会丢帧,调用重绘,并不会马上执行,只是等到下次vsync信号来的时候才会执行,所以什么时候发起绘制操作没有太大关系,并不会丢帧
上面讨论了屏幕刷新大致流程,接下来说下与屏幕相关的Surface绘制原理
那什么是Surface绘制,具体都做了哪些操作呢,绘制原理如下
应用需要绘制,首先创建Surface,但Surface需要buffer,它需要在SurfaceFlinger中创建BufferQueue,这个BufferQueue中有很多buffer,每个buffer对应一个Surface,buffer有两端,一个producer端,一定要跨进程传回给Surface进行保管 ,另一个consumer端,Surface要进行绘制,需要通过producer端进行bind调用,向BufferQueue中申请一块buffer,绘制完成后返回给BufferQueue,BufferQueue就会通知consumer端回调,表示又有一帧数据好可以,用来消费这一帧数据
其实Surface中有两个buffer,一个是前台用来显示的buffer,另一个是用来绘制的后台buffer,互不影响,后台绘制好后切换到前台进行显示
说道Surface的buffer,那不得不谈一谈buffer相关内容
通过GraphicBufferProducer向buffer申请
通过GraphicBufferProducer向buffer进行提交的
它不是buffer,只是一个壳子,内部包含可以生产buffer的对象,就是GraphicBufferProducer
Surface还可以进程跨进程传递数据
是传递GraphicBufferProducer对象
activity在第一次进行绘制的时候会在performTraversals中申请Surface
系统中创建是SurfaceControl对象,并不是Surface对象,SurfaceControl中有GraphicBufferProducer,就可以创建Surface,然后返回给应用
最后再说一下vsync机制相关内容
通过接口回调给上层
一种通过HWComposer进程硬件生成,另一种通过VsyncThread进行软件生成。都是分发给DispSyncThread工作线程。这个工作线程又会分发给app-EventThread(App进程)线程,另一个是sf-EventThread(SurfaceFlinger自己使用)
一方面分发个应用进程,另一方面分发给SurfaceFlinger。主要是因为一方面通知应用进行绘制UI,另一个方面通知SurfaceFlinger对图像进行合成与渲染操作。分开分发避免同时抢占CPU资源
学习完以上内容,我们对整个UI刷新流程,及刷新涉及的相关知识点,有了一定的了解,以上内容只是大致给出了结论,我们再通过阅读相关源码,将会对整个UI刷新有了更深的认识