leak_tracker 是 dart 官方检测内存泄露的工具,目前文档还不够完善。 之前一直是在测试用例里用的,以后应该还会集成到官方的 devtools 里面,现在可以在 app debug 模式下用了。
集成到app非常简单:
void main() async {
_initLeakTracking();
runApp(const MyApp());
}
//在 debug 模式下会持续检查内存溢出情况,其他模式下无效果
//https://github.com/dart-lang/leak_tracker/blob/main/doc/leak_tracking/CONCEPTS.md
void _initLeakTracking() {
//打印保存堆栈信息
LeakTracking.phase = const PhaseSettings(
leakDiagnosticConfig: LeakDiagnosticConfig(
collectRetainingPathForNotGCed: true,
collectStackTraceOnStart: true,
collectStackTraceOnDisposal: true));
LeakTracking.start(config: LeakTrackingConfig(onLeaks: (s) async {
//打印当前内存溢出整体情况
debugPrint("onLeak: ${s.toJson()}");
//收集所有内存溢出异常,调用这个方法后会清空LeakTracking里的所有已收集的异常
final leaks = await LeakTracking.collectLeaks();
//一些组件需要在 Widget 回收之后调用其 dispose 方法,通过此可以检测出未调用 dispose 方法的组件
//a disposable object was GCed, without being disposed first.
//This means that the object's disposable content is using memory after the object is no longer needed.
for (var n in leaks.notDisposed) {
debugPrint(n.toYaml("内存溢出检查 notDisposed:", phasesAreTests: true));
}
//统计未进行内存回收的对象
//an object was disposed, but not GCed after certain number of GC events.
//This means that a reference to the object is preventing it from being garbage collected after it's no longer needed.
for (var n in leaks.notGCed) {
debugPrint(n.toYaml("内存溢出检查 notGCed:", phasesAreTests: true));
}
//统计对象进行了内存回收,但是回收时间不及时
//an object was disposed and then GCed, but GC happened later than expected.
//This means the retaining path was holding the object in memory for some period, but then disappeared.
for (var n in leaks.gcedLate) {
debugPrint(n.toYaml("内存溢出检查gcedLate:", phasesAreTests: true));
}
}));
FlutterMemoryAllocations.instance.addListener(
(ObjectEvent event) => LeakTracking.dispatchObjectEvent(event.toMap()));
}
dependencies:
flutter:
sdk: flutter
...
# 内存溢出检测工具
leak_tracker: ^10.0.5