Lottie内存泄漏问题的定位与分析

发表于:2020-7-06 10:16

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:baiyang    来源:搜狗测试

  一、前言Lottie简介与使用
  1、Lottie简介
  Lottie是Airbnb开源的跨平台动画库,支持iOS、Android、React Native 和 Web 等平台。它可以解析使用 Bodymovin 导出为 json 的 Adobe After Effects 动画,允许应用程序像使用静态图像一样轻松使用动画。
  Android库地址:https://github.com/airbnb/lottie-android
  iOS库地址:https://github.com/airbnb/lottie-ios
  Lottie资源库:https://lottiefiles.com/
  2、Lottie的使用流程
  (1).动效设计人员在Adobe After Effects中设计动画;
  (2).动效设计人员通过Adobe After Effects的Bodymovin插件导出记录动画信息的JSON文件;
  (3).开发人员使用Lottie的开源库读取这份JSON文件进行解析和渲染。
  3、Lottie方案的优点
  (1).动画由设计使用专业的动画制作工具Adobe After Effects来实现,使动画实现更加方便,动画效果也更好,100% 还原。
  (2).使用lottie方案,json文件大小会比gif文件小很多,性能也会更好。
  (3).简单的实现、控制动画的播放,开发效率大大提高。
  (4).可动态配置下发,实时替换动画效果。
  4、lottie-android 两种引入方式
  xml方式
  编程方式
  5、Lottie实现原理
  Lottie使用通过Bodymovin插件导出的json文件作为动画数据源,(json文件把图片中的元素进行来拆分,并且描述每个元素的动画执行路径和执行时间)。Lottie的读取这些数据,然后绘制到屏幕上。
  首先要解析json,建立数据到对象的映射,然后根据数据对象创建合适的Drawable绘制到view上,动画的实现可以通过操作读取到的元素完成。具体过程如下所示
  json文件——>Component——>Drawable——>View
  通过如下3个核心类来来完成整个工作流程
  (1).LottieComposition(json->数据对象)
  Lottie使用LottieComposition来作为After Effects的数据对象,即把Json文件映射为到LottieComposition,该类中提供了解析json的静态方法
  (2).LottieDrawable(数据对象->Drawable)
  绘制
  Lottie 的核心是 LottieDrawable,它承载了所有的绘制工作,LottieAnimationView则是对LottieDrawable 的封装,再附加了一些例如解析的功能。
  (3).LottieAnimationView(绘制)
  操作集合,LottieAnimationView继承自 AppCompatImageView,封装了一些动画的操作,具体的绘制委托 LottieDrawable 完成的。
  二、内存泄漏问题背景出现场景
  背景
  输入法录音助手SDK测试,录音助手SDK和输入法进程相互独立。
  问题场景
  (录音助手SDK)首页和(输入法)我的页面切换,发现明显的内存增长趋势。
  问题修复插曲
  开发同学的账号和机器泄漏不明显,修复其他内存泄漏后,开发提交检验;但测试同学机器和账号内存泄漏易复现,最终开发测试一同对比定位,复现。
  问题修复
  修复后,(助手SDK)首页和(输入法)我的页面切换,最终退出SDK,可见内存最终可以恢复平稳,和起始内存差异不大;助手SDK进程的CPU占用0%。
  三、问题定位与分析
  结论:lottie本身的状态处理有bug 导致泄漏了,MemoryLeak in LottieDrawable。
  lottieview在detach的时候会停止动画,如果无法停止,就会导致内存泄漏。
  小编场景分析:
  进首页->退出,很有可能动画还没开始,就要被停止掉,所以就释放不了资源。
  代码分析
  lottie依赖onDetachedFromWindow停止动画,动画的play可能是异步的,在onDetachedFromWindow 中会判断当前是否在动画中,如果在动画中才会停止动画,删除异步任务,但此时可能并不再动画中,但有一个已经post出去的异步任务,在detach 后动画会执行。
  加载动画是异步的,加载完成才会进入播放状态。如果compositionLayer == null 的时候,会加入到task里,没开始播放。
  播放开始了running= true;
  removeFrameCallback,running = false;
  onDetachedFromWindow停止动画
  detach 处理时,先判断是不是播放状态,如果是播放状态running == true,才会去 cancel。但有可能加载动画完成发生在 detach 之后。
  官方:Lottie的新版本修改了这个问题,但Lottie 3.0.0以上版本必须要项目支持android X。
  评估:这个改动需要把所有第三方框架都进行升级,对小编所在项目成本太高,暂不可行。
  目前处理:重写LottieAnimationView继承,然后在ondetachedfromwindow里直接cancle。无论是否在动画中都调用一次 cancelAnimation, 取消动画,删除可能存在的异步任务。


      本文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号