Android中“无效背景动画”的行为分析但是当用户知道你和一个app退到后台后还在做无效动画,而这个动画是完全没有意义的,用户并不知道他在做动画和消耗用户可怜的电池,至少被多任务杀死,禁止后台运行,严重的直接卸载。普通开发者很难发现这个问题,但是如果你经常使用Systrace,打开几十个应用程序然后回到桌面,左右滑动抓取Systrace,你很容易发现后台总有那么几个应用程序。经常做无效动画。这里所说的背景动画,是指由于某种原因,应用退回到后台后,当用户看不到任何App界面时,仍然在后台不断更新,消耗CPU。这个问题可能有很多原因。毕竟Choreographer中抛出CALLBACK_ANIMATION的地方太多了,每个应用可能都不一样,但最终每个应用都需要修复。下面我们举两个例子,从技术角度来看一下事件发生时的情况和原因。我希望阅读本文的开发人员检查他们的应用程序是否存在此问题,将网易新闻退到后台,然后在桌面左右滑动,抓取Systrace可以看到:网易新闻退到后台后继续做Animation回调(红框内),每一帧还在doFrame中手术。放大每个doFrame可以看到,Choreographer中的输入和遍历都没有被触发,只是执行了动画回调。我们把这个Trace上所有的cpu部分都选中,然后按照下面的WallDuration排序,可以发现网易新闻后台动画执行时间最长。当应用程序已经在后台并且不可见时,它仍然如此频繁地工作,占用CPU资源并耗电。确实不合适,抓取相应的MethodTrace看是在做动画不关闭,而且动画还在每一帧做onAnimationUpdate的回调,可以看出这是使用了Lottie的库导致的Airbnb,动画没有关闭,所以触发实例还在做——QQ音乐启动QQ音乐,然后回到桌面,左右滑动桌面抓取Systrace和MethodTrace,可以看到和网易新闻的表现同上。在抓取QQ音乐的背景动画时,MethodTrace发现也是退到后台后没有暂停动画导致的。也是Airbnb的Lottie惹的祸,QQ音乐三部动画还没停,比网易新闻还严重。放大后就可以看到了,当然也不是全是Airbnb的Lottie动画库造成的。比如下面这个就是普通动画没有结束的根本原因。不可见后,动画并没有暂停,导致应用切换到后台,动画的回调还在刷新,但是此时因为不可见,InputCallback和drawCallback不会被触发,所以不会有绘制操作,也就是说动画刷新是完全没有意义的(当然也可能是业务需求?)上面两个例子中网易新闻和QQ音乐都是使用Lottie导致的实现动画,但没有正确关闭它。开发建议Lottie库的问题列表里有人提到了这个情况:提出问题:我最近对一个使用lottie做一些动画(自动播放和循环)的应用程序做了一些基准测试。我注意到当应用程序在后台并尝试调查时,CPU使用率相当高。在我看来,当包含的LottieAnimationView离开屏幕和/或Activity暂停时,循环动画不会暂停/停止。我相信这是因为清理代码只在onDetachedFromWindow()中,一旦Activity进入暂停状态就不一定被调用,而且当视图不再可见(GONE,INVISIBLE)时绝对不会被调用。解决方法:覆盖LottieAnimationView并执行以下操作为我解决了可见性问题,Lottie在不可见时暂停。@OverrideprotectedvoidonVisibilityChanged(@NonNullViewchangedView,intvisibility){super.onVisibilityChanged(changedView,visibility);if(visibility==VISIBLE&&wasAnimatingWhenVisibilityChanged){resumeAnimation();}else{if(isAnimating()){wasAnimatingWhenVisibilityChanged=true;pauseAnimation();}else{wasAnimatingWhenVisibilityChanged=false;}}}简而言之:当App不可见时,停止所有动画:pauseAnimation!!!
