AlanJereb.com
Coding

Flutter – Detecting memory leaks – Leak Tracker

May 25th, 2025

This is the fourth and final blog post in the

Flutter – Detecting memory leaks

series. If you haven’t done so yet, I warmly suggest that you start with the

.

On September 1st 2022, Polina Cherkasova made the first commit to her newly tasked Dart-lang project called

. This core Flutter team member was given the task of creating a tool that would help detect non-disposed and non-garbage-collected objects.

The plan for this tool is to be included in the Dart DevTools once completed, but at the time of writing this article, it still hasn't been officially released (My active versions:

Flutter 3.27.1

,

Dart 3.6.0

,

DevTools 2.40.2

). As the documentation is nearly non-existent, I had to scour through the source code to understand how it works and how somebody can use it.

The goal of this article is to teach you how you can use it.

What is Dart Leak Tracker, and how does it work?

Dart team’s idea behind this package is simple. The package helps to identify and diagnose memory leaks in Dart applications.

Key

fe

a

tur

es:

  • detect: identify not needed objects that are retained in memory-related
  • visualise: provide a GUI (graphical user interface) for easier visualisation in Dart DevTools
  • filter: give the ability to track specific types of objects or all objects
  • analyse: provide information about why objects are being retained (retaining paths)

How does it work?

Reading the code, I’ve identified a handful of places where I’ve noticed Leak Tracker’s methods being called on non-self-disposing object creation. If Leak Tracker is instantiated, it will:

  • monitor object allocation and garbage collection
  • identify which objects survive longer than expected
  • track retaining paths to help analyse why objects aren’t being collected
  • provide reports through Dart DevTools

Flutter SDK code example - ImageInfo object creation tracking

Flutter SDK code example - TrainHoppingAnimation object creation tracking

Flutter SDK code example - TextSelectionOverlay object creation tracking

How can you use Dart Leak Tracker before the official release?

How can you use Dart Leak Tracker before the official release? The documentation for setup on the official GitHub repository is outdated and no longer works. By fixing a bug in Dart Leak Tracker (

wasn’t merged yet), piecing together a few code snippets from a 2-year-old Reddit post and a few GitHub issues, I’ve managed to make it work.

To use Dart Leak Tracker inside your Flutter application, you must first fix the bug in the Dart Leak Tracker code. Navigate to where your

dart-lang

package is installed on your machine and open the

pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart

file. You need to fix the filter that filters leaks that are garbage collected late.

LeakType.gcedLate: _objects.gcedLateLeaks
  // .where((record) => _leakFilter.shouldReport(LeakType.notGCed, record)) fixed
  .where((record) => _leakFilter.shouldReport(LeakType.gcedLate, record))
  .map((record) => record.toLeakReport())
  .toList(),
}); 

Next, if you are using my code from the previous blog post in the series, replace the

main.dart

file contents with the contents found

. If you are looking for leaks in your app, make sure to add the following to your

main.dart

file (skip the steps if you are using my code):

1. Instantiate leak_tracker

You need to import the required dependencies, and before the

runApp

is called, you need to instantiate the Leak Tracking package.

import 'package:flutter/foundation.dart';
import "package:leak_tracker/leak_tracker.dart";

void main() {
  LeakTracking.start();
  FlutterMemoryAllocations.instance.addListener((ObjectEvent event) {
    LeakTracking.dispatchObjectEvent(event.toMap());
  });
  runApp(const MyApp());
}

2. Collect the leaks functionality

You need to implement a mechanism that will collect the currently observed leaks and return them to you. In my demo app, I have modified the

TextButton

’s onPressed callback so that it also collects the leaks.

onPressed: () async {
  Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const HomePage()));
  await Future.delayed(const Duration(milliseconds: 500)); // let the leak_tracker settle
  Leaks leaks = await LeakTracking.collectLeaks();
  print("Leaks collected");
},

Run the app, do things that usually produce memory leaks, and then try to collect them. The quickest way to observe what has been collected is to place a breakpoint and check what was assigned to the

leaks

variable.

Is your code still leaking?

Keep in mind that

leak_tracker

package has not yet released, and it is possible that it didn’t find the culprit for your leaks.

Why didn’t leak_tracker find your leaks?

  • Polina is yet to include your leaking objects in the list of observed objects
  • It might just be that your leak originates somewhere that not even the Flutter team is aware of. It might be a bug in the Flutter framework or even the Dart language that causes leaks.

Now comes the hard part. The only thing remaining is to produce and analyse your app's memory dump. Memory dump analysis is out of scope for this blog post series, but I will happily

with you.