精选文章

Flutter 内存优化实战

2021-04-01 · 内存

内存问题不是“用一阵子就变慢”,而是“应用增长过程中必然出现的工程成本”。本篇从内存结构、诊断流程、泄漏定位到图片缓存优化,给你一套能直接落地的实践路线。

1. 内存问题的三类根因

常见内存问题可以分为:

  • 缓存过大:图片、网络数据、列表预渲染
  • 对象堆积:全局单例持有引用,生命周期不回收
  • 重复创建:大量短生命周期对象高频创建

目标不是“消灭内存”,而是把内存维持在稳定区间,避免持续增长。

2. 诊断流程:先确认增长曲线

基本流程:

  1. 进入典型高压页面(图片/列表/富文本)
  2. 使用 DevTools 的 Memory 视图观察堆曲线
  3. 触发 GC,看是否能回落

如果曲线持续上升且 GC 后不回落,基本可以判定泄漏。

3. 典型泄漏源:全局引用

最常见的泄漏场景是“全局持有引用”。

class CacheStore {
  CacheStore._();
  static final CacheStore instance = CacheStore._();

  final Map<String, Object> _cache = {};

  void put(String key, Object value) {
    _cache[key] = value;
  }

  void clear() {
    _cache.clear();
  }
}

问题:如果不清理,缓存会一直增长。
建议:给缓存上限,或用 LRU 策略。

class LruCache<K, V> {
  LruCache(this.maxSize);

  final int maxSize;
  final _map = <K, V>{};

  void put(K key, V value) {
    if (_map.length >= maxSize && !_map.containsKey(key)) {
      _map.remove(_map.keys.first);
    }
    _map[key] = value;
  }

  V? get(K key) => _map[key];
}

4. 图片缓存优化:避免无上限增长

Flutter 默认图片缓存是 ImageCache,可以通过 PaintingBinding 控制。

void configureImageCache() {
  final cache = PaintingBinding.instance.imageCache;
  cache.maximumSize = 200; // 图片数量限制
  cache.maximumSizeBytes = 80 * 1024 * 1024; // 80MB
}

建议:

  • 列表页使用缩略图
  • 大图只在详情页加载
  • 超大图片优先压缩再显示

5. 列表与滚动的内存控制

列表内存问题多来自 item 过大或无限缓存。

ListView.builder(
  cacheExtent: 600,
  itemBuilder: (context, index) => ItemCard(index: index),
  itemCount: 500,
);

建议:

  • cacheExtent 适当设置
  • item 尽量轻量,避免深层嵌套

6. 实战小结:稳定曲线才是优化成功

你要追求的不是“内存最低”,而是:

  • 内存增长可控
  • GC 后能回落
  • 长时间使用保持稳定
JJ

作者简介

专注于内容创作、产品策略与设计实践。欢迎交流合作。

上一篇 下一篇