Why is this memory leaking?

Viewed 352

In this example, each time I press "Click", 50M of ram is allocated. It is never reclaimed, I can push 30 pages and take up 1.5gb, despite there only ever being 1 page on the nav stack. GC never kicks in. What's going on here?

Flutter (Channel master, 2.1.0-11.0.pre.122, on Microsoft Windows [Version 10.0.18363.1440], locale en-US)

void main() {
  runApp(MaterialApp(
    home: MemoryTest(),
  ));
}

class MemoryTest extends StatelessWidget {
  final List<EdgeInsets> insets = List.generate(
    1000000,
    (index) => EdgeInsets.all(0),
  );
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Column(
        children: [
          OutlinedButton(
            child: Text("CLICK"),
            onPressed: () {
              Navigator.of(context).pushReplacement(MaterialPageRoute(
                builder: (_) => MemoryTest(),
              ));
            },
          ),
        ],
      ),
    );
  }
}
2 Answers

The answer here is twofold. On one hand, its a bug, and the flutter team is working on it: https://github.com/flutter/flutter/issues/79605

The actual cause for the bug here seems to actually be the closure, wrapping context which is forcing the stateless widget to stay in memory forever.

If you avoid the context in the closure, by caching the navigator as a local var, the leak doesnt happen. Obviously most Flutter devs are not doing this, and many code examples directly from Flutter also do this, so hopefully the team can fix this.

U should move ListItem inside the function build

class MemoryTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
  final insets = List.generate(
    1000000,
    (index) => EdgeInsets.all(0),
  );
    return Container(
      color: Colors.white,
      child: Column(
        children: [
          OutlinedButton(
            child: Text("CLICK"),
            onPressed: () {
              Navigator.of(context).pushReplacement(MaterialPageRoute(
                builder: (_) => MemoryTest(),
              ));
            },
          ),
        ],
      ),
    );
  }
}
Related