内存泄漏分析总结

一、背景

测试人员发现一个问题,就是反复快速进入详情页就会导致详情页崩溃,或者是app图标全部不可见。

二、解决过程

首先初步判断肯定是有性能问题,要么是内存太大,要么是内存泄漏了。

1.我们通过devTools查看彩页内存

image.png

a、点击Menory。b、多次反复进入退出页面。c、点击GC主动挥手回收对象。d、筛选我们的页面

发现存在多个页面对象。肯定是内存泄漏了

2.初步解决一些常见的内存泄漏问题

a、图片占用内存过大有可能导致内存泄漏,对图片做了一系列优化,防止内存过大;以及把图片相关需要释放的都在页面关闭时释放掉。

b、把页面里面其他需要释放的一些对象,全部释放掉了,减少部分内存泄漏。

经过测试,之前几次就会导致页面内存爆炸,现在需要三十多次才会导致内存爆炸。

3.还有其他内存泄漏源,继续查找

初步怀疑是getx框架有问题,所以在尝试getx哪里有问题。发现getx中的_routesKey会直接会导致页面不会被释放掉,加了如下一行代码,可以释放掉页面。

image.png

修改后,有的是可以释放掉页面,有的仍然无法释放。

所以getx确实会导致页面无法释放,导致内存泄漏,但是代码里面也还存在内存泄漏。

4.继续查找页面里面内存泄漏

由于页面中组件有几十个,设计的面积比较广,所以很难直接定位到。于是进一和我继续通过devtools查看内存以及对比内存差异,期望找到突破点。但是内存里面的对象有上百个,很难定位到底是哪一个,起初还误以为是attr和loader,因为他们泄漏很多对象。但是实际很难说是他们泄漏导致页面泄漏,还是页面泄漏导致这些对象泄漏。

最后我开始分析页面返回的数据,决定一个卡片去试,通过devtools分析可以判断出是哪一个卡片泄漏,找到卡片泄漏后,再一个组件去试,找到Image组件导致内存泄漏,最后再通过局部注释代码,最终定位到PreviewPptInheritWidget

class _PImageWidgetState extends State<PImageWidget> {
  ui.Image? _rawImageContent;
  ClipClipper? _oldClipper;
  double? themeRadius;
  PreviewPptInheritWidget? _previewPptInheritWidget;
  ...
  @override
  void initState() {
      _previewPptInheritWidget = PreviewPptInheritWidget.ofUnDepend(context);
      super.initState();
  }
  ...
  }

PreviewPptInheritWidget就是一个InheritedWidget子类,所以他是PImageWidge的父类。在PImageWidge持有PreviewPptInheritWidget对象,就会导致循环引用,最终导致内存泄漏。

所以大家后续如果使用InheritedWidget系列组件,最好不要持有(成员变量),如果非要持有,就需要在dispose的时候把InheritedWidget系列对象置空。

ios的同学可能非常熟悉循环引用,android同学之前几乎遇不到循环引用,android的同学可能要特别注意。

----------------------后续补充-------------------
后续又发现采用navigator.pop()退出页面不会出现内存泄漏。
如果是使用navigator.removeRoute()退出后台的某个页面,只会关闭页面,但是页面会出现内存泄漏。
大概是pop会去回收页面等完整流程,removeRoute只是移除路由。
有对这个十分了解的同学,也可以评论区交流

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容