硬件加速
Android 3.0 (API level 11)开始,Android 2D渲染管道支持硬件加速。API level >=14的Android系统默认开启硬件加速。由于硬件加速并不支持所有的2D绘制操作,所以开启硬件加速,可能会导致自定义view中部分元素看不到,程序抛出异常,或者错误的像素渲染等问题。
开启/关闭硬件加速
- Application
<application android:hardwareAccelerated="true" ...>
- Activity
<application android:hardwareAccelerated="true">
<activity ... />
<activity android:hardwareAccelerated="false" />
</application>
- Window 级别只能开启硬件加速
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
- View 关闭硬件加速
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
View硬件加速的判断
两个方法:
你必须在你绘制代码(drawing code)内检测,使用前者而不是后者,因为有可能View虽然依附于一个硬件加速的窗口,但它依然可以在一个没有硬件加速的Canvas上绘制,列如:为了缓存的目的把view绘制到一个bitmap上。
Android 软加速/硬加速 绘制模式
基于软件的绘制模式
绘制步骤:无效从下到上的View,然后重新绘制。
问题:
- 没有改变的大量上层的View需要重新绘制。
- Android重绘view的过程,有可能没有绘制发生改变的view,此时你只能依赖其他view包含恰好的重绘行为。
硬件加速的绘制模式
绘制步骤:
- 无效从下到上的View
- 记录和更新显示列表(display lists)
- 绘制显示列表
优点: 使用display lists能有针对性的更新改变的View
不支持的绘制操作
Canvas Scaling
View Layers
Off-screen buffers
- a view's drawing cache
- [Canvas.saveLayer()](https://developer.android.com/reference/android/graphics/Canvas.html#saveLayer(android.graphics.RectF, android.graphics.Paint))
所有的Android版本都支持对Off-screen buffers进行渲染。
你会获得更好的性能,当做复杂view的动画或者应用合成效果时。列如,当你实现淡出效果时,你可以使用Canvas.saveLayer(),暂存渲染的view到layer中,然后用透明度合成,使它返回屏幕达到淡出效果。
[View.setLayerType()](https://developer.android.com/reference/android/view/View.html#setLayerType(int, android.graphics.Paint))
- LAYER_TYPE_NONE 不使用 off-screen buffer 【默认】
- LAYER_TYPE_HARDWARE
- LAYER_TYPE_SOFTWARE
选择技巧
- Performance: 使用硬件加速时,一旦一个view渲染进如layer中,只有调用invalidate()是绘制的代码才会被执行。一些动画,列如透明度动画,可以直接用于layer中,这使用GPU去执行是非常高效的。
- Compatibility: Use a software layer type to force a view to be rendered in software.
View layers and animations
如果你在你的应用中跑的动画没有达到,你想要的流程结果,你可以考虑启动硬件加速。 以下的属性,使用合成来作用于layer,使用的是优化的invalidation及不需要重绘目标view,过程更高效。
- alpha: Changes the layer's opacity
- x, y, translationX, translationY: Changes the layer's position
- scaleX, scaleY: Changes the layer's size
- rotation, rotationX, rotationY: Changes the layer's orientation in 3D space
- pivotX, pivotY: Changes the layer's transformations origin
demo:
View.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY", 180);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
view.setLayerType(View.LAYER_TYPE_NONE, null);
}
});
animator.start();
提示和技巧
- 减少view的数量
- 避免过度绘制
A good rule of thumb with current hardware is to not draw more than 2.5 times the number of pixels on screen per frame (transparent pixels in a bitmap count!). - 不创建渲染类在绘制代码中:如在onDraw中 new Paint 或者 Path。
- 不频繁的改变形状
Complex shapes, paths, and circles for instance, are rendered using texture masks. Every time you create or modify a path, the hardware pipeline creates a new mask, which can be expensive. - 不频繁的修改bitmap
- 谨慎使用alpha,当应用alpha属性到很大的views时,考虑使用 LAYER_TYPE_HARDWARE。
.