V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
OneAPM
V2EX  ›  Android

如何从软硬件层面提升 Android 动画性能?

  •  3
     
  •   OneAPM · 2015-12-10 14:03:53 +08:00 · 8454 次点击
    这是一个创建于 3272 天前的主题,其中的信息可能已经有所发展或是发生改变。

    若是有人问如何解决动画性能不佳的问题,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/

    3 条回复    2015-12-10 14:58:40 +08:00
    comicfans44
        1
    comicfans44  
       2015-12-10 14:36:33 +08:00
    看了下,原文地址可没有 OneAPM Mobile Insight 这个分析工具的广告
    comicfans44
        2
    comicfans44  
       2015-12-10 14:57:22 +08:00
    没注意到楼主就是作者..不好意思
    hjc4869
        3
    hjc4869  
       2015-12-10 14:58:40 +08:00
    强行全文转载并在别人有 copyright 的文章里插入自己的广告。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2808 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 07:35 · PVG 15:35 · LAX 23:35 · JFK 02:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.