Android 硬件加速简介

硬件加速的原理

将view的绘制函数转化成OpenGL中的函数来完成绘制。

软件绘制与硬件绘制的区别

  • 软件绘制
    在软件绘制模式,view是按照下面两个步骤进行绘制的:
  1. 无效化View层次结构
  2. 绘制View的层次结构

绘制的特点:
当应用需要更新它的一部分UI,它会调用view的invalidate方法,无效化消息就会通过各种途径传递到View的层次结构,然后计算屏幕中需要重绘的区域(脏区域),android系统还会对View层次结构中脏区域相交的所有view进行绘制。

不足:
1. 这个模式在每一次绘制都需要执行大量的代码,比如,如果你的应用对一个button调用invalidate,而这个button坐标在其他view的上方,那么android系统就会重绘这些view,即使他们没有发生改变,仅仅因为它们处于和button相交的区域。
2. 由于一个view的绘制可能导致另一个view重绘,因此会引起一些不被注意到的bug。

  • 硬件绘制
    新的绘制模式包含三个步骤:
  1. 无效化View的层次结构
  2. 记录和更新显示列表
  3. 绘制显示列表

android系统依然使用invalidate和draw函数来请求屏幕刷新渲染界面,但实际上绘制的时候是有区别的,不同于立即执行绘制命令,android系统会先把它们记录在display list上,这个display lists包含view的层次结构的绘制代码。其他的优化是android系统只需要记录和更新display lists,通过调用invalidate函数来标记那些脏view,那些没有被标记为invalidate的view可以简单的进行重绘通过事先记录在display list上的记录。

举个栗子:
例如,假设有一个LinearLayout在Button上面有一个ListView,那么对于LinearLayout的display list就会像这样的:
DrawDisplayList(ListView)
DrawDisplayList(Button)
假设现在你通过调用setAlpha(0.5)来修改ListView的透明度,那么display list就变成这样了:
SaveLayerAlpha(0.5)
DrawDisplayList(ListView)
Restore
DrawDisplayList(Button)

关于ListView的复杂的绘制代码并没有被执行,系统只是更新了LinearLayout的display list,如果应用没有启用硬件加速,那么listview以及它的父容器LinearLayout的绘制代码都会再次执行。

硬件加速的优势

  • 流畅性更好:切换到硬件加速,界面固然是更加流畅了,但是我们开发应用的时候要想让GPU的效率更加的高。

  • 性能更好:硬件加速的优势在于display list这个设计,使用这个的话,我们就不需要每次重绘都执行大量的代码,因为对脏区域的,基于软件的绘制模式会重绘脏区域内的所有控件,而display只会更新列表,然后绘制列表内的控件。

硬件加速的弊端

  • 消耗更多的内存:由于要把系统中OpenGL加载到内存,所以OpenGL API调用就会占用8MB,而实际上会占用更多内存,并且使用了硬件必然增加耗电量了。
  • 兼容性:硬件加速是从API 11引入,API 14之后才默认开启。对于标准的绘制操作和控件都是支持的,但是对于自定义View的时候或者一些特殊的绘制函数就需要考虑是否需要关闭硬件加速。

tips

  • 1.当你的应用是硬件加速的,硬件图层类型可以传达更快和更加顺滑的动画,当你在处理的是一个复杂的又很多绘制操作的view的时候,运行一个动画不总是60帧每秒的。可以通过使用硬件层来渲染view到一个硬件的texture中来优化这个问题,硬件texture可以用来对view进行动画,排除开始动画的时候需要重绘自己的View,view不会重新重绘除非你改变它的属性,然后调用invalidate()。
    如果你运行一个动画在你的应用上,但是得不到一个你想要的顺滑结果,考虑启用硬件加速在你的动画view上。当view从硬件图层回退的时候,它的一些属性会通过图层合成到屏幕上的方式进行处理,设置这些属性将会更加高效,因为它不需要view重绘或者无效化。
    因为硬件层消耗video存储,所以强烈建议启用它们只有在动画时长并且关闭它们当动画完成的时候,你可以完成这个通过使用动画监听器,这一个比较细节,但能够对View进行优化,毕竟手机内存这么少。
    示例代码应该是这样
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();
  • 2. 小心使用alpha属性
    当你使用setAlpha,或者AlphaAnimation,或者ObjectAnimator来改变一个View的透明度时,它渲染在离屏缓存中需要两倍填充率,当需要在在一个非常大的view上修改alpha,就要考虑设置view的layer type为LAYER_TYPE_HARDWARE。

你可能感兴趣的:(Android 硬件加速简介)