![67426a1e7eb4e86514a3e07b050c2b27.png](https://i-blog.csdnimg.cn/blog_migrate/9ab6fd774a96a0b9331ba7369a3008b3.jpeg)
屏幕刷新机制
与屏幕刷新相关的有很多,比如刷新流程,屏幕缓存,周期刷新,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绘制
Android刷新频率60帧/秒,每个16ms调用onDraw方法?
刷新屏幕指的是vsync信号的屏幕,但是不是每次vsync都去绘制,需要应用发起重绘,向SurfaceFlinger
请求vsync信号,这样在下一次vsync信号来的时候,才会进行绘制
onDraw完后屏幕会马上刷新吗
屏幕并不会立即刷新,需要等到下次vsync信号来的时候才会进行刷新
如果界面没有重绘,还会每隔16ms刷新屏幕吗
如果界面没有进行重绘,并不会收到vsync信号进行重绘,但是屏幕还会每隔16ms进行重绘,不过用的数据是旧图像数据,看起来屏幕没有变化
如果在屏幕快要刷新的时候才会去绘制会丢帧吗
不会丢帧,调用重绘,并不会马上执行,只是等到下次vsync
信号来的时候才会执行,所以什么时候发起绘制操作没有太大关系,并不会丢帧
Surface 绘制原理
上面讨论了屏幕刷新大致流程,接下来说下与屏幕相关的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相关内容
Surface绘制的buffer怎么来的
通过GraphicBufferProducer
向buffer申请
buffer绘制完了又是怎么提交的
通过GraphicBufferProducer
向buffer进行提交的
怎么理解Surface,它是一块buffer吗
它不是buffer,只是一个壳子,内部包含可以生产buffer的对象,就是GraphicBufferProducer
Surface 跨进程传递
Surface还可以进程跨进程传递数据
Surface到底是怎么跨进程传递的
是传递GraphicBufferProducer
对象
Activity的Surface是怎么跨进程传递的
activity在第一次进行绘制的时候会在performTraversals
中申请Surface
Activity的Surface在系统中创建后,是怎么跨进程传回应用的?
系统中创建是SurfaceControl
对象,并不是Surface对象,SurfaceControl
中有GraphicBufferProducer
,就可以创建Surface,然后返回给应用
Vsync 机制
最后再说一下vsync机制相关内容
Vsync信号的生成机制
通过接口回调给上层
Vsync在SurfaceFlinger中分发流程
一种通过HWComposer
进程硬件生成,另一种通过VsyncThread
进行软件生成。都是分发给DispSyncThread
工作线程。这个工作线程又会分发给app-EventThread(App进程)
线程,另一个是sf-EventThread(SurfaceFlinger自己使用)
Vsync信号分发原理
一方面分发个应用进程,另一方面分发给SurfaceFlinger
。主要是因为一方面通知应用进行绘制UI,另一个方面通知SurfaceFlinger
对图像进行合成与渲染操作。分开分发避免同时抢占CPU资源
总结
学习完以上内容,我们对整个UI刷新流程,及刷新涉及的相关知识点,有了一定的了解,以上内容只是大致给出了结论,我们再通过阅读相关源码,将会对整个UI刷新有了更深的认识