Flutter 内存优化详解
简介
内存优化对于保持应用流畅运行至关重要。本文介绍如何优化 Flutter 应用的内存使用。
内存泄漏
常见原因
- 未释放的监听器
- 全局变量引用
- 定时器未取消
- Stream 未关闭
- 动画控制器未释放
检测方法
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();
});
}
}
最佳实践
- 及时释放资源
- 优化图片加载
- 实现列表懒加载
- 限制缓存大小
- 监控内存使用
注意事项
- 避免内存泄漏
- 控制图片缓存
- 优化大列表
- 处理生命周期
- 监控性能指标
总结
内存优化需要从多个方面入手,包括资源管理、图片优化、列表优化等。通过合理的优化措施,可以显著提升应用的性能和稳定性。