情况
我开始为Android开发,并发现Android处理布局,动画等方式不足以实现流畅的触摸反馈和实时动画,尤其是在Android 4.0之前。因此,我决定使用游戏应用程序方法:使用SurfaceView
并定义我自己的绘图代码。
问题
经过几次测试后,我发现这种方法对非游戏应用程序需要太多的CPU,我相信这是因为每秒重绘60次静态元素。
第一个解决方案&缺陷
要解决此问题,我修改了代码,以便只有在应该绘制的内容发生任何更改时,应用才会重绘屏幕(调用postInvalidate
)。这个解决方案解决了部分问题,但即使一个小按钮移动了一个像素,app仍然需要重绘静态元素。
问题:可能更好的解决方案?
为了更好的解决方案,我考虑了Android如何处理这个问题;它为每个屏幕元素分别有View
个。所以我想,也许我可以有一个SurfaceView
用于大型静态内容元素,另一个用于移动的小UI元素,并实现类似的效果。我的问题是,这会不会像我上面描述的那样提高性能?
感谢。
答案 0 :(得分:2)
如果您正在使用postInvalidate()
,则应该使用custom View,而不是SurfaceView。使用SurfaceView的重点是拥有一个独立于View UI的独立层。如果您要覆盖onDraw()
,则需要在View部件上绘图,而不是在Surface部件上绘图,只是浪费Surface。
无论您拥有多少视图,所有视图都占用一个图层。每个SurfaceView都有一个单独的层,因此有很多层将成为问题。在实践中,由于Z排序限制,您可以不超过三个。 (有关与View UI混合的三个部分透明SurfaceView的示例,请参阅"多表面测试" Grafika中的活动。)
如果您无法快速渲染以保持60 fps,则需要考虑更改渲染方式。自定义视图和OpenGL ES利用硬件加速。 Canvas渲染到SurfaceView Surface上不会。从好的方面来说,您可以缩小SurfaceView的Surface尺寸并让硬件将其重新调整;这使您可以限制每帧绘制的像素数,无论显示器的分辨率如何。 (Blog,demo。)如果你有很多静态元素,最好的方法可能是渲染到屏幕外的Bitmap,然后每帧都只是blit Bitmap。
一种非常快的方法是将所有静态元素渲染到SurfaceView的View部分,注意保持背景透明,然后使用GLES渲染Surface上的动画部分。您可以使用第二个SurfaceView,但会增加一个额外的合成图层,如果超过硬件支持的叠加层数,这将降低系统性能。
要更深入地了解Android图形的工作方式,请查看graphics architecture doc。