Flutter images memory does not get gc

2,327

Image widget retains cached images and does not release the memory under certain circumstances. That's a known issue and as of Nov 2, 2020 is still opened.

You can check it with DevTools Profiling if you look at the _Int64List variable. It's growing when you update your image with new instances.

enter image description here

As a workaround for now we're manually clearing the cache on every build() and on dispose():

 PaintingBinding.instance.imageCache.clear();
 PaintingBinding.instance.imageCache.clearLiveImages();
Share:
2,327
Panda World
Author by

Panda World

Just super awesome

Updated on December 17, 2022

Comments

  • Panda World
    Panda World over 1 year

    I have a page widget to display a long list of images using Image.network() on android device. After a long scroll and gets every image displayed, the memory has gone up quite a lot to 200MB. The app is working fine atm and then I leave the page, dispose() called. The memory usage, however, is still not reduced.

    enter image description here

    as you can see from the graph, the external memory is occupying 186MB of space and never goes down. I read the devTool doc that external memory is native objects. But why aren't they garbage collected? Or maybe that is just the android way of managing memory?

    Please check below my sample code. I'm placing it at the tabbarviews, when I select another tab, the page get disposed.

    class TestScreen extends StatefulWidget {
      const TestScreen({Key key}) : super(key: key);
    
      @override
      createState() => _TestScreenState();
    }
    
    class _TestScreenState extends State<TestScreen> with SingleTickerProviderStateMixin {
    
      List<Product> products = [];
    
      @override
      void initState() {
        super.initState();
        print("initState");
        fetchProducts();
      }
    
      @override
      void dispose() {
        print("dispose");
        super.dispose();
      }
    
      Future fetchProducts() async {
        //get the list of products
        setState(() {
          products = ...;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        ThemeData theme = Theme.of(context);
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Scaffold(
          body: GridView.builder(
              itemCount: products.length,
              padding: EdgeInsets.all(4.0),
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 2,
                  mainAxisSpacing: 2.0,
                  crossAxisSpacing: 2.0,
                  childAspectRatio: 0.8),
              itemBuilder: (context, position) {
                final product = products[position];
                final imageData = product.mainImage;
                if (imageData != null && imageData.downloadURL != null) {
                  return Image.network(
                    imageData.downloadURL,
                    fit: BoxFit.fill,
                  );
                } else {
                  return Image.asset("assets/images/product_image_placeholder.jpg");
                }
              }),
          ),
        );
      }
    }
    
    • Amir
      Amir about 4 years
      i think you should clean image cache
    • Panda World
      Panda World about 4 years
      @veneno could you please put up your example code?
    • Amir
      Amir about 4 years
      PaintingBinding.instance.imageCache.clear(); try it before dispose
    • Panda World
      Panda World about 4 years
      @veneno it works! thank you, Sir. I have one more question, is it safe to just leave the memory cache like it is and let it manage itself? I have not idea how memory management works underneath in this case.
  • Bermjly Team
    Bermjly Team over 2 years
    Unfortunately your workaround is not fixing the issue.