Freelancing for Pale Blue

Looking for flexible work opportunities that fit your schedule?


Image.file() widget not refreshing

Flutter Oct 10, 2020

Anyone knowing about the basics of how Flutter decides what to redraw when setState is called will know about keys. So in theory, if you have unique keys for your widgets, you will get your UI to redraw, right?

Image not refreshing

The problem occurred when I was building a very basic UI for a prototype. Just a ListView with Image widgets inside. The Image widgets are read from a location in the disk.

ListView.builder(
        itemCount: pages.length,
        itemBuilder: (BuildContext context, int index) =>
            Image.file(
              File(pages[index]),
              key: UniqueKey(),
            ));

Since the widget has a UniqueKey(), I was expecting that every time setState is called, even if pages array remained the same, the latest images would be shown in the UI.

This was not the case though. No matter what I tried, the same image that was loaded the first time would be displayed in the UI, even if I changed the contents of the files (but not their file name or location).

If I tried to create new images and use different names every time, then the UI would work as expected. But this was quite inconvenient and unnecessary. Was there something I was missing on how the framework worked?  

Image cache

It turns out that Flutter is using a global image cache that I was not aware of. Of course, this was mentioned in Image.file() constructor DartDoc but I was too lazy to read. Other people hit this issue as well.

The framework was indeed re-drawing the widgets since they had a UniqueKey(). It was just using the in-memory copy of the image because the image path was the same and was considering it the same image.

The solution is just to clear the cache in combination with setting a UniqueKey().

imageCache.clear();
imageCache.clearLiveImages();

[...]

ListView.builder(
        itemCount: pages.length,
        itemBuilder: (BuildContext context, int index) =>
            Image.file(
              File(pages[index]),
              key: UniqueKey(),
            ));

If you are using multiple images in your app, clearing the entire cache every time might be inefficient. You can look into removing specific entries from the cache using evict() (thanks ren3f!).

Hopefully, I will save someone else a few hours of debugging. Happy coding!

Tags

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.