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

2020/07/03 17:17
阅读数 3.8K
点击
“搜狗测试”
可关注我们!

【一、前言Lottie简介与使用


 1Lottie简介

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/

2Lottie的使用流程

(1).   动效设计人员在Adobe After Effects中设计动画;

(2).   动效设计人员通过Adobe After Effects的Bodymovin插件导出记录动画信息的JSON文件;

(3).   开发人员使用Lottie的开源库读取这份JSON文件进行解析和渲染

3Lottie方案的优点

(1).    动画由设计使用专业的动画制作工具Adobe After Effects来实现,使动画实现更加方便,动画效果也更好,100% 还原。

(2).   使用lottie方案,json文件大小会比gif文件小很多,性能也会更好。

(3).    简单的实现、控制动画的播放,开发效率大大提高。

(4).    可动态配置下发,实时替换动画效果。

4lottie-android 两种引入方式

xml方式

编程方式

5Lottie实现原理

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, 取消动画,删除可能存在的异步任务。

【参考


Lottie 官方文档:http://airbnb.io/lottie/

Lottie Github:https://github.com/airbnb/lottie-android

https://zhuanlan.zhihu.com/p/41339812

https://juejin.im/entry/58a324d12f301e00695da316

https://juejin.im/post/5a31ea836fb9a0451705367c

https://juejin.im/post/5d19fb53e51d45598611b9b6


欢迎添加我们的搜狗测试微信号,与我们一起聊聊测试


本文分享自微信公众号 - 搜狗测试(SogouQA)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部