使用多个表面视图进行优化?

Using Multiple Surfaces Views For Optimization?

情况

我开始为 Android 开发,发现 Android 处理布局、动画等的方式不足以实现流畅的触摸反馈和实时动画,尤其是在 Android 4.0。因此,我决定使用游戏应用程序方法:使用 SurfaceView 并定义我自己的绘图代码。

问题

经过几次测试,我发现这种方法对于非游戏应用程序来说需要太多CPU,我认为这是因为每秒重绘静态元素 60 次。

第一个解决方案和缺陷

为解决此问题,我修改了我的代码,以便应用程序仅在应绘制的内容发生任何更改时重绘屏幕(调用 postInvalidate)。这个解决方案解决了部分问题,但是即使一个小按钮移动了一个像素,应用程序仍然需要重新绘制静态元素。

问题:可能的更好解决方案?

为了更好的解决方案,我考虑了Android如何处理问题;每个屏幕元素都有单独的 View。所以我虽然,也许我可以有一个 SurfaceView 用于大的、静态的、内容元素,另一个用于小的、移动的 UI 元素,并达到类似的效果。我的问题是,这真的会像我上面描述的那样提高性能吗?

谢谢。

  1. 如果您使用 postInvalidate(),您应该使用 custom View,而不是 SurfaceView。使用 SurfaceView 的全部意义在于拥有一个独立于 View UI 的单独层。如果你重写 onDraw(),你是在视图部分上绘制,而不是表面部分,只是在浪费表面。

  2. 无论您有多少视图,所有视图都占据一个层。每个 SurfaceView 都有一个单独的层,因此拥有很多 SurfaceView 会出现问题。实际上,由于 Z 顺序的限制,您不能超过三个。 (请参阅 Grafika 中的 "multi-surface test" activity 以了解三个部分透明的 SurfaceView 与视图 UI 混合的示例。)

  3. 如果渲染速度不足以保持 60 fps,则需要考虑更改渲染方式。自定义视图和 OpenGL ES 利用硬件加速。 Canvas 渲染到 SurfaceView Surface 不会。从好的方面来说,您可以缩小 SurfaceView 的 Surface 并让硬件按比例放大它;这使您可以限制每帧必须绘制的像素数,而不管显示器的分辨率如何。 (Blog, demo.) 如果你有很多静态元素,最好的方法可能是渲染到屏幕外的位图,然后每帧 blit 位图。

一种非常快速的方法是将所有静态元素渲染到 SurfaceView 的视图部分,注意保持背景透明,然后使用 GLES 在 Surface 上渲染动画部分。您可以使用第二个 SurfaceView,但这会添加一个额外的合成层,如果您超过硬件支持的覆盖平面数量,这将降低系统性能。

要更深入地了解 Android 图形的工作方式,请查看 graphics architecture doc