Flutter页面跳转时携带大图数据内存剧增问题排查

业务需求是从相册中选择一张小于5兆的图片,然后到第二个页面进行编辑,测试过程中发现当选择大一些的图片时,程序可能会出现崩溃。

选择一张3.6兆的图片进行测试,发现内存增长到了4个G。

由于项目中使用的是GetX进行页面跳转的。一开始以为是Getx框架出现的问题,阅读源码,发现最终调用的也是flutter原生的路由。

于是尝试使用使用原生跳转传参方式

Navigator.pushNamed(
  Get.context!,
  '/target3',
  arguments: {'imageBytes': imageBytes},
);

经过测试发现和使用Getx进行路由跳转一样会内存爆增。

跟踪Flutter源码,路由参数会封装成 RouteSettings

final RouteSettings settings = RouteSettings(
  name: name,
  arguments: arguments,
);


重写了toString方法,将arguments转化为了String。

@immutable
class RouteSettings {

  const RouteSettings({
    this.name,
    this.arguments,
  });

  final String? name;

  final Object? arguments;

  @override
  String toString() => '${objectRuntimeType(this, 'RouteSettings')}(${name == null ? 'none' : '"$name"'}, $arguments)';
}

在dart中,字符串模式使用​UTF-16 编码,每个字符占用 ​2 字节,经过测试,一张3.6MB的jpg图片 转成位图之后是48.59MB,转成字符串之后是231.07MB。在路由跳转的时候还会打印参数内容,当231.07MB的字符串数据提交到日志系统时,应用就会变得非常卡顿,严重的直接造成崩溃。

如果修改toString源码,arguments不包含进去,再重新测试,就会发现可以少占用2G左右的内存。

class RouteSettings {

  const RouteSettings({
    this.name,
    this.arguments,
  });

  final String? name;

  final Object? arguments;

  @override
  String toString() => 'print test';
}

除了日志打印之外,路由跳转的过程中,还多次进行了json encode

settingsJsonable['arguments'] = jsonEncode(
   settings.arguments,
   toEncodable: (Object? object) => '$object',
);

每拷贝一个对象都会多231兆的内存占用,所以在路由跳转的过程中,如果携带过大的byte数据,会导致内存剧增,超出内存边界时,应用直接崩溃。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值