zoukankan      html  css  js  c++  java
  • 如何从软硬件层面提升 Android 动画性能?

    若是有人问如何解决动画性能不佳的问题,Dan Lew Codes 总会反问:你是否使用了硬件层?

    动画放映过程中每帧画面可能都要重绘。如果使用视图层,,渲染过的视图可以存入离屏缓存以待将来重用,而无需每帧重绘。

    此外,硬件层缓存与 GPU 中,这使得动画放映中的某些操作更加快速。简单的转换(平移,旋转,缩放,开端)可通过硬件层快速渲染。由于许多动画只是这些转换的组合,使用硬件层可大大提高动画性能。

    Usage

    应用

    硬件层 API 十分简单:使用 View.setLayerType()即可。硬件层设定只能暂时使用,因为它们并非没有代价(下文会有更多相关介绍)。基本过程如下:

    1. 动画过程中,对每个需要缓存的视图调用View.setLayerType(View.LAYER_TYPE_HARDWARE, null)
    2. 运行动画
    3. 动画结束时,使用 View.setLayerType(View.LAYER_TYPE_NONE, null)清除缓存。

    以下为上述过程的具体实施:

    // Set the layer type to hardware                   
    myView.setLayerType(View.LAYER_TYPE_HARDWARE, null); 
    
    // Setup the animation 
    ObjectAnimator animator = ObjectAnimator.ofFloat(myView, View.TRANSLATION_X, 150); 
    
    // Add a listener that does cleanup 
    animator.addListener(new AnimatorListenerAdapter() {   
      @Override  
      public void onAnimationEnd(Animatoranimation){
        myView.setLayerType(View.LAYER_TYPE_NONE, null);
      } 
    }); 
    
    // Start the animation 
    animator.start();  
    

    如果你使用 minSdkVersion 16以上版本与ViewPropertyAnimator,可用简便的withLayer()代替上述方法。

    myView.animate()     
    .translationX(150)  
    .withLayer()   
    .start();
    

    这样做之后,动画变得很流畅!

    警告

    …你也知道,事实并非如此简单。

    硬件层在提高动画性能方面能力优异。然而,如果使用不当,也可能弊大于利。千万不要盲目使用硬件层!

    首先,在很多情况下,硬件层实际进行的操作可能不止于简单的视图渲染。缓存硬件层的耗时不少,因为第一步其实包含两个过程:一、把视图渲染进 GPU 的层中。二、GPU 将该层渲染为视窗。如果该视图渲染比较简单(例如色彩单一),硬件层可能在初始过程中导致非必要的内存开销。

    第二,对于所有缓存,都存在缓存失效的可能。在动画过程中,如果有人调用了 View.invalidate(),则硬件层不得不再次渲染。经常这样做事实上比没有硬件层还要糟糕,因为(如前所述)硬件层在初始化缓存时会增加内存开销。如果经常性地二次缓存硬件层,势必影响动画性能!

    由于动画经常包括多个移动部件,该问题极易发生。假定你在设置一个具有三个移动部件的动画。

    父 ViewGroup

    -->子视图1(向左平移)
    -->子视图2(向右平移)
    -->子视图3(向上平移)

    假使你在父ViewGroup 配置了单独的硬件层,会造成缓存持续失效,这是因为ViewGroup(作为整体)由于其子视图的变化而持续改变。然而,每个独立的视图来说,只是在平移而已。因此,最好为每个子视图(而非父容器)配置硬件层。重申一点:为多个视图配置硬件层,可保证其在动画过程中不失效。

    “展示硬件层更新”是用于追踪此类问题的好工具。每当视图渲染硬件层时,它会使视图闪现绿色。在动画开始时(即硬件层初始渲染)时它只会闪光一次。然而,如果你的视图在整个动画过程中一直呈现绿色,说明你遇到缓存失效问题了。

    第三,硬件层会占用GPU存储空间,你当然不想出现内存泄露。所以,你只应在必要时使用硬件层,比如动画展示过程。

    综上所述-并不存在硬性规则。安卓渲染系统是复杂的,经常让我吃惊。对于所有性能问题,检测是关键。“GPU渲染分析”和“硬件层更新展示”设置能用于有效判断硬件层的作用好坏。

    举例

    我写了一个例子以演示硬件层的基本应用。你可以在此处得到源码

    以下是启用GPU渲染分析设置后,应用在GalaxyNexus(一个又老又慢的设备)上的运行结果

    enter description here

    没有硬件层,如此简单的动画也非常糟糕,经常性地位于绿线之上意味着应用性能简直是一团乱麻。相反,使用了硬件层的版本则一直在绿线之下-太棒了!

    第三个案例展示了动画中使用硬件层但是缓存失效造成的危害。因为误使硬件层,许多性能提升也毁于一旦。(奇怪之处在于-如果它缓存失效,为什么并不像没有使用硬件层那样慢呢?虽然我也无法完全理解个中缘由,但显然,即使它每一步都要重绘,硬件层还是带来一些有利的优化。不过,最好还是正确地使用硬件层。)

    这个故事要的主旨是:硬件层的确有利于提升动画性能,但必须正确使用之。

    软件层优化

    从硬件层面进行了优化,那么如何从软件层面进行快速定位及优化呢?

    使用OneAPM可以快速定位分析UI性能,Mobile Insight的卡顿可以直观地展示这些信息。
    卡顿趋势图
    可以分析绘制APP卡顿趋势图,精确定位每1秒内的绘图刷新信号中断的次数,从多维度分析卡顿现象,如APP版本、操作系统版本的分布情况等。
    卡顿分布
    卡顿详情列表展示:访问时间,发生卡顿时的流畅度,耗时,发生卡顿时的设备信息,APP版本,操作系统及版本,CPU信息
    通过分析该页面信息可以清楚了解到卡顿来源,以便针对性快速优化。
    卡顿详情

    动画卡顿原因

    动画卡顿的原因大概有这样三种,这些因素将直接影响动画的性能,导致卡顿。即:

    1. 手势滑动速度
    2. 帧率
    3. 触摸事件响应的速度

    手势滑动、帧率是跟各种手机设备有直接的关系,各种各样的硬件设备会表现出不一样的性能,如果从这个方面入手考虑优化,就十分需要 OneAPM Mobile Insight 这样的从多维度来分析性能的一款工具。

    原文地址:http://blog.danlew.net/2015/10/20/using-hardware-layers-to-improve-animation-performance/

  • 相关阅读:
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    微信小程序TodoList
    C语言88案例-找出数列中的最大值和最小值
    C语言88案例-使用指针的指针输出字符串
  • 原文地址:https://www.cnblogs.com/oneapm/p/5035429.html
Copyright © 2011-2022 走看看