Flutter内存泄漏检测插件flutter_leak_canary的使用

Flutter内存泄漏检测插件flutter_leak_canary的使用

step 1

首先,需要配置VsCode或Android Studio以设置运行参数--disable-dds

在VsCode或Android Studio的配置文件中添加以下内容:

"configurations": [
    {
        ...
        "args": [
            "--disable-dds"
        ],
        "type": "dart"
    },
]

或者通过图形界面进行配置:

config

step 2

接下来,在需要检测内存泄漏的类中添加LeakCanaryStateMixinLeakCanarySimpleMixin

class _WeakPageState extends State<WeakPage> with LeakCanaryStateMixin {
  //...
}

class TestModel with LeakCanarySimpleMixin {
  Timer? timer;
  int count = 0;

  init() {
    watch();
    timer = Timer.periodic(Duration(seconds: 1), (timer) {
      count++;
      print("TestModel $count");
    });
  }

  void dispose() {
    timer?.cancel();
    try2Check();
  }
}

示例

以下是一个完整的示例代码,展示了如何使用flutter_leak_canary插件来检测内存泄漏。

import 'dart:isolate';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter_leak_canary/flutter_leak_canary.dart';
import 'package:flutter_leak_canary/leak_canary_state_mixin.dart';
import 'package:flutter_leak_canary/leak_cannary_model.dart';
import 'package:flutter_leak_canary_example/weak_page.dart';
import 'package:intl/intl.dart';

void main() {
  runApp(_MyApp());
}

class _MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyApp(),
    );
  }
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  [@override](/user/override)
  void initState() {
    super.initState();
    initPlatformState();
    FlutterLeakCanary.get().addListener(_onChange);
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      Navigator.push(context, MaterialPageRoute(builder: (context) {
        return WeakPage();
      }));
    });
  }

  List<LeakCanaryWeakModel> canaryModels = [];

  _onChange() {
    if (mounted) {
      setState(() {
        canaryModels = FlutterLeakCanary.get().canaryModels;
      });
    }
  }

  [@override](/user/override)
  void dispose() {
    super.dispose();
    FlutterLeakCanary.get().removeListener(_onChange);
  }

  // 平台消息是异步的,因此我们在异步方法中初始化。
  Future<void> initPlatformState() async {
    String platformVersion;
    // 平台消息可能会失败,所以我们使用try/catch处理PlatformException。
    // 我们还处理消息可能返回null的情况。
    try {
      'Unknown platform version';
    } on PlatformException {
      platformVersion = 'Failed to get platform version.';
    }

    // 如果小部件从树中被移除,而异步平台消息还在飞行中,我们希望丢弃回复而不是调用setState更新我们的非存在的外观。
    if (!mounted) return;

    setState(() {});
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('插件示例应用'),
      ),
      body: ListView.builder(
        itemCount: canaryModels.length,
        itemBuilder: (BuildContext context, int index) {
          final canaryModel = canaryModels[index];
          return Container(
            padding: EdgeInsets.symmetric(horizontal: 10),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                    '${DateFormat("yyyy-MM-dd HH:mm:ss").format(DateTime.fromMillisecondsSinceEpoch(canaryModel.createTime))}'),
                Text('file:${canaryModel.classFileName}', style: TextStyle(color: Colors.lightBlue),),
                Text('class name:${canaryModel.className}', style: TextStyle(color: Colors.red),),
                Text('location>column:${canaryModel.column},line:${canaryModel.line}', style: TextStyle(color: Colors.redAccent),),
                SizedBox(
                  height: 5,
                ),
                Container(
                  width: double.infinity,
                  height: 1,
                  color: Color(0xFFf5f5f5),
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

更多关于Flutter内存泄漏检测插件flutter_leak_canary的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter内存泄漏检测插件flutter_leak_canary的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


flutter_leak_canary 是一个用于检测 Flutter 应用中内存泄漏的插件。它类似于 Android 开发中的 LeakCanary,可以帮助开发者发现和修复内存泄漏问题。以下是 flutter_leak_canary 的基本使用步骤:

1. 添加依赖

首先,在你的 pubspec.yaml 文件中添加 flutter_leak_canary 依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_leak_canary: ^1.0.0  # 使用最新版本

然后运行 flutter pub get 来安装依赖。

2. 初始化插件

在你的应用的 main.dart 文件中初始化 flutter_leak_canary

import 'package:flutter/material.dart';
import 'package:flutter_leak_canary/flutter_leak_canary.dart';

void main() {
  // 初始化 LeakCanary
  FlutterLeakCanary.setup();

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

3. 检测内存泄漏

flutter_leak_canary 会自动检测内存泄漏,并在控制台输出相关信息。你可以通过在代码中手动触发检测来验证其功能:

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Leak Canary Demo'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // 创建一个可能会泄漏的对象
            final leakyObject = LeakyObject();
            // 手动触发内存泄漏检测
            FlutterLeakCanary.detectLeaks();
          },
          child: Text('Trigger Leak Detection'),
        ),
      ),
    );
  }
}

class LeakyObject {
  // 一个可能会泄漏的对象
}

4. 查看检测结果

当你运行应用并触发内存泄漏检测时,flutter_leak_canary 会在控制台输出类似于以下的信息:

LeakCanary: Leak detected!
LeakCanary: Object reference: LeakyObject@12345678
LeakCanary: Leak trace:
LeakCanary:   at _MyHomePageState.build (main.dart:30)
LeakCanary:   at StatefulElement.build (framework.dart:4612)
LeakCanary:   at ComponentElement.performRebuild (framework.dart:4546)
...

通过这些信息,你可以定位到内存泄漏的源头,并进行修复。

5. 配置选项(可选)

flutter_leak_canary 提供了一些配置选项,你可以根据需要进行调整:

FlutterLeakCanary.setup(
  enableLogging: true,  // 是否启用日志输出
  dumpHeap: true,       // 是否在检测到泄漏时 dump 堆内存
);

6. 处理检测到的泄漏

根据 flutter_leak_canary 输出的信息,你可以找到泄漏的对象和引用链,然后通过以下方式修复:

  • 确保不再使用的对象被正确释放。
  • 避免在全局或长生命周期的对象中持有短生命周期对象的引用。
  • 使用 WeakReference 来避免强引用导致的泄漏。

7. 在生产环境中禁用

flutter_leak_canary 主要用于开发和调试阶段,建议在生产环境中禁用,以避免不必要的性能开销。你可以通过以下方式在生产环境中禁用:

void main() {
  if (!kReleaseMode) {
    FlutterLeakCanary.setup();
  }
  runApp(MyApp());
}
回到顶部