如何从软硬件层面提升 Android 动画性能? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
OneAPM
V2EX    Android

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

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

    若是有人问如何解决动画性能不佳的问题,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     Solana     1625 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 16:17 PVG 00:17 LAX 08:17 JFK 11:17
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86