公告

👇欢迎大家关注公众号&私信交流👇

Skip to content

Flutter 内存优化详解

简介

内存优化对于保持应用流畅运行至关重要。本文介绍如何优化 Flutter 应用的内存使用。

内存泄漏

常见原因

  1. 未释放的监听器
  2. 全局变量引用
  3. 定时器未取消
  4. Stream 未关闭
  5. 动画控制器未释放

检测方法

dart
// 使用 flutter_memory_profiler 监控内存
import 'package:flutter_memory_profiler/flutter_memory_profiler.dart';

void main() {
  FlutterMemoryProfiler.init();
  runApp(MyApp());
}

优化方法

1. 资源释放

dart
class ResourceManager {
  Timer? _timer;
  StreamSubscription? _subscription;
  AnimationController? _controller;
  
  void initialize() {
    // 创建定时器
    _timer = Timer.periodic(Duration(seconds: 1), (_) {
      // 定时任务
    });
    
    // 订阅流
    _subscription = stream.listen((_) {
      // 处理数据
    });
    
    // 创建动画控制器
    _controller = AnimationController(vsync: this);
  }
  
  void dispose() {
    _timer?.cancel();
    _subscription?.cancel();
    _controller?.dispose();
  }
}

2. 图片优化

dart
// 1. 使用缓存
class CachedNetworkImageWrapper extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CachedNetworkImage(
      imageUrl: 'https://example.com/image.jpg',
      memCacheWidth: 300, // 缓存尺寸限制
      memCacheHeight: 300,
      maxWidthDiskCache: 600, // 磁盘缓存限制
      maxHeightDiskCache: 600,
    );
  }
}

// 2. 图片预加载
Future<void> precacheImages() async {
  final images = [
    'image1.jpg',
    'image2.jpg',
    'image3.jpg',
  ];
  
  for (var image in images) {
    await precacheImage(
      AssetImage('assets/images/$image'),
      context,
    );
  }
}

3. 列表优化

dart
// 1. 使用 ListView.builder
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(items[index].title),
    );
  },
);

// 2. 懒加载数据
class LazyLoadingList extends StatefulWidget {
  @override
  _LazyLoadingListState createState() => _LazyLoadingListState();
}

class _LazyLoadingListState extends State<LazyLoadingList> {
  final List<String> _items = [];
  final ScrollController _controller = ScrollController();
  bool _loading = false;
  
  @override
  void initState() {
    super.initState();
    _loadMore();
    _controller.addListener(() {
      if (_controller.position.pixels == 
          _controller.position.maxScrollExtent) {
        _loadMore();
      }
    });
  }
  
  Future<void> _loadMore() async {
    if (_loading) return;
    
    setState(() => _loading = true);
    
    // 模拟加载数据
    await Future.delayed(Duration(seconds: 1));
    setState(() {
      _items.addAll(List.generate(20, (i) => 'Item ${_items.length + i}'));
      _loading = false;
    });
  }
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      controller: _controller,
      itemCount: _items.length + 1,
      itemBuilder: (context, index) {
        if (index == _items.length) {
          return _loading
              ? Center(child: CircularProgressIndicator())
              : SizedBox();
        }
        return ListTile(title: Text(_items[index]));
      },
    );
  }
}

完整示例

dart
class MemoryOptimizedApp extends StatelessWidget {
  final ImageCacheManager imageCacheManager = ImageCacheManager();
  final ResourceManager resourceManager = ResourceManager();
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: [
            // 优化图片加载
            CachedImage(
              url: 'https://example.com/image.jpg',
              placeholder: CircularProgressIndicator(),
              errorWidget: Icon(Icons.error),
              cacheManager: imageCacheManager,
            ),
            
            // 优化列表
            Expanded(
              child: LazyLoadingList(),
            ),
          ],
        ),
      ),
    );
  }
}

// 图片缓存管理
class ImageCacheManager {
  static const int maxMemoryCacheSize = 100;
  
  ImageCacheManager() {
    PaintingBinding.instance.imageCache.maximumSize = maxMemoryCacheSize;
  }
  
  void clearCache() {
    PaintingBinding.instance.imageCache.clear();
    PaintingBinding.instance.imageCache.clearLiveImages();
  }
}

// 自定义图片组件
class CachedImage extends StatelessWidget {
  final String url;
  final Widget placeholder;
  final Widget errorWidget;
  final ImageCacheManager cacheManager;
  
  const CachedImage({
    Key? key,
    required this.url,
    required this.placeholder,
    required this.errorWidget,
    required this.cacheManager,
  }) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return Image.network(
      url,
      frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
        if (wasSynchronouslyLoaded) return child;
        return frame == null ? placeholder : child;
      },
      errorBuilder: (context, error, stackTrace) => errorWidget,
      cacheWidth: 300,
      cacheHeight: 300,
    );
  }
}

内存监控

DevTools

dart
// 启用 DevTools 内存监控
void main() {
  if (kDebugMode) {
    debugProfileMemoryUsage();
  }
  runApp(MyApp());
}

自定义监控

dart
class MemoryMonitor {
  static void logMemoryUsage() {
    if (kDebugMode) {
      final usage = ProcessInfo.currentRss;
      print('Memory usage: ${usage ~/ 1024 ~/ 1024}MB');
    }
  }
  
  static void startPeriodicLogging() {
    Timer.periodic(Duration(seconds: 5), (_) {
      logMemoryUsage();
    });
  }
}

最佳实践

  1. 及时释放资源
  2. 优化图片加载
  3. 实现列表懒加载
  4. 限制缓存大小
  5. 监控内存使用

注意事项

  1. 避免内存泄漏
  2. 控制图片缓存
  3. 优化大列表
  4. 处理生命周期
  5. 监控性能指标

总结

内存优化需要从多个方面入手,包括资源管理、图片优化、列表优化等。通过合理的优化措施,可以显著提升应用的性能和稳定性。