maui icon indicating copy to clipboard operation
maui copied to clipboard

Image caching should be configurable for all ImageSources

Open ClemensFischer opened this issue 3 years ago • 40 comments

Description

When using StreamImageSource on Android, image cache files are written to a folder named image_manager_disk_cache in FileSystem.CacheDirectory.

Looking for a way to disable this behavior, I found that in src/Core/AndroidNative/maui/src/main/java/com/microsoft/maui/PlatformInterop.java the methods loadImageFromFile, loadImageFromStream and loadImageFromFont always pass true to the cachingEnabled argument of the loadInto method.

This seems wrong. Caching should be configurable, as it is implemented for loading an image from an URI string.

Public API Changes

Add a CachingEnabled and a CacheValidity property to the classes FileImageSource, StreamImageSource and FontImageSource, similar to the respective properties in UriImageSource. Perhaps move those properties into their common base class.

Usage:

var imageSource = new StreamImageSource
{
    Stream = ...,
    CachingEnabled = false
};

Alternatively, disable caching for those ImageSources. It seems pointless to cache an image file that is loaded from a local file or stream or font symbol.

Intended Use-Case

In my map control library I am downloading map tiles images via HTTP from map content providers like OpenStreetMap or Bing Maps. It uses StreamImageSource to create ImageSource objects from the HTTP response stream or buffer.

The library implements its own map tile image caching mechanism and does not need any further caching.

ClemensFischer avatar Aug 30 '22 11:08 ClemensFischer

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

ghost avatar Aug 30 '22 13:08 ghost

I would really like to see this issue addressed whenever possible. My app contains a number of images streamed from byte arrays, none of which images can be visibly deleted on user request, apparently because of caching. Only when the page is closed and re-opened is it apparent a deletion occurred. Even worse, after a deletion, when the user tries to add back an image, the old cached one appears. He then has to try the add again to get it replaced. Setting image source to null or to an image source from a stream of byte[0] has no effect. A very disgusting situation!!

DavidPressman avatar Sep 02 '22 20:09 DavidPressman

To clarify: What I just described is as seen on Android. Not sure about other platforms.

DavidPressman avatar Sep 02 '22 20:09 DavidPressman

I am using StreamImageSource to load map tile images from different content providers for a map control. My observation was that (on Android) sooner or later the control began to show wrong images from the cache. Generation of cache keys is obviously broken, and should be fixed.

My current workaround is to always clear the image cache after an ImageSource was created:

var imageManagerDiskCache = Path.Combine(FileSystem.CacheDirectory, "image_manager_disk_cache");

if (Directory.Exists(imageManagerDiskCache))
{
    foreach (var imageCacheFile in Directory.EnumerateFiles(imageManagerDiskCache))
    {
        Debug.WriteLine($"Deleting {imageCacheFile}");
        File.Delete(imageCacheFile);
    }
}

ClemensFischer avatar Sep 05 '22 05:09 ClemensFischer

Why it takes so long to fix such a big bug ? What's the workaround to disable ?

AHComp avatar Oct 07 '22 13:10 AHComp

  • Showing wrong thumbnail from cache: Sometimes wrong thumbnail image showing in collection view (multi-threading)
  • Privacy leak: writing thumbnails of encrypted media file (image, video) to disk plainly. This is serious problem for privacy applications.

rentanadviser avatar Dec 28 '22 09:12 rentanadviser

This is like p0, maybe p1. Definitely not something for the backlog.

H-A-Hristov avatar Jan 26 '23 13:01 H-A-Hristov

This explains why my local profile picture system keeps loading older profile pictures

Mielesgames avatar Jan 31 '23 12:01 Mielesgames

This is a pretty big issue. Looks like @ClemensFischer gave you the code to change, what's the holdup? Android image caching is messed up right now and needs addressing.

rbrettj avatar Feb 18 '23 09:02 rbrettj

Very big issue! @jfversluis this is a breaking issue - an upgrade might be needed

stiaan-netup avatar Mar 14 '23 12:03 stiaan-netup

Looks like we have #13111 already merged. Does that look like it would cover this case as well?

jfversluis avatar Mar 14 '23 15:03 jfversluis

Hi @ClemensFischer. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

ghost avatar Mar 14 '23 15:03 ghost

@jfversluis That is for StreamImageSource only. It still seems pretty pointless to have caching enabled for FileImageSource and FontImageSource.

ClemensFischer avatar Mar 14 '23 15:03 ClemensFischer

File caching isn't pointless. Its a good feature. Especially when a mobile device suddenly lost internet connection. Or if you want to limit your bandwith usage. However this issue requested to make caching customizable so it can be turned off when needed doesn't change existing behavior. I dont think that like #13111 caching here should be turned off as well without giving devs the choice to turn it back on. These are two different scenarios.

Symbai avatar Mar 14 '23 17:03 Symbai

@Symbai That is not true, Loading an image via FileImageSource means that it is loaded from a local image file. Creating another local image file in the cache makes no sense at all. When you say "lost internet connection" you are talking about remote image resources, which are loaded via UriImageSource.

ClemensFischer avatar Mar 14 '23 17:03 ClemensFischer

It still seems pretty pointless to have caching enabled for FileImageSource and

Caching a file image source in memory saves you disk I/O time. The underlying library that handles the caching (Glide) does multiple types of caching; it's not just caching to disk. It will also cache images in memory where appropriate.

I agree with your overall point - you should be able to disable caching if you want for a given image source. And we should have overloads which let you customize the keys which are used for caching*. But that would require new APIs, so it's not likely to happen until a major version release.

* (Keys are why #13111 had to turn off caching for streams entirely. URIs and files have natural useful keys; streams don't, so Glide was always re-using images when it shouldn't have been because we weren't giving it decent keys to work with. Until we can design and implement an API that allows users to pass in usable keys for caching streams, we have to turn off caching for them or they won't work at all.)

hartez avatar Mar 14 '23 21:03 hartez

@hartez We are not talking about memory cache here. This issue is about cache files in a folder named image_manager_disk_cache in FileSystem.CacheDirectory. This is what just should not be done.

The suggested API change would be easy and compatible: add a CachingEnabled and a CacheValidity property to the classes FileImageSource, StreamImageSource and FontImageSource. Can't see anything complicated with that.

However, I do not really care anymore since I gave up on MAUI, at least for now. May try again next year or so to see if it has evolved into a more mature platform.

ClemensFischer avatar Mar 14 '23 21:03 ClemensFischer

Is there a workaround for this on Android? I am loading an image from file, the image is then changed (keeps the same filename), but the Image is still showing the old image.

idiidi avatar May 02 '23 14:05 idiidi

Workaround is to save image as temporary file to disk and give it a unique(!) name. Then load the image from this unique filename.

Symbai avatar May 02 '23 16:05 Symbai

wondering if there's any update on this? We have a product mid way through UAT testing for a client and this is an issue for images we generate from static SVG data in our database via API. We're generating ~110 small PNG files from the SVG data each time a change is detected in our static tables using the excellent SkiaSharp library . Giving each one a unique name such as DevOps pipeline build number would be ok but doesn't feel the right thing to do to allow end users to slowly fill up their app folder with old images they won't use anymore. This is only an issue for Android, iOS seems to pick up the image changes immediately.

edgedj avatar Jul 20 '23 19:07 edgedj

This is also breaks our app. We have Image with FontImageSource that FontFamily can be changed. Basically as of right now MAUI is enabled cache by default this make FontImageSource still use old FontFamily. Like now, workaround is doing this https://github.com/dotnet/maui/issues/9773#issuecomment-1236550801 but I do hope this getting fixed. Xamarin.Forms app I believe don't have this issue (maybe Xamarin.Forms not enable caching by default for FontImageSource)

albilaga avatar Aug 03 '23 09:08 albilaga

wondering if there's any update on this? We have a product mid way through UAT testing for a client and this is an issue for images we generate from static SVG data in our database via API. We're generating ~110 small PNG files from the SVG data each time a change is detected in our static tables using the excellent SkiaSharp library . Giving each one a unique name such as DevOps pipeline build number would be ok but doesn't feel the right thing to do to allow end users to slowly fill up their app folder with old images they won't use anymore. This is only an issue for Android, iOS seems to pick up the image changes immediately.

Image caching is disabled for images loaded from a stream in the latest versions of MAUI. So you could load those images from streams rather than from files - that would avoid caching.

hartez avatar Aug 07 '23 19:08 hartez

Image caching is disabled for images loaded from a stream in the latest versions of MAUI.

Caching should still also be configurable for image files. This is such a ridiculously simple change, why don't you just implement it instead of letting this discussion go on for months? @hartez

ClemensFischer avatar Aug 07 '23 19:08 ClemensFischer

@ClemensFischer 100% agree, complete screws so many apps but no update. @hartez We have to release an Android app by Nov 1 with this bug because there is not other option. MS have dropped the ball on this one. Such a large part of the community need this! Sorry, no justification for it considering so many Xamarin apps are being ported over to Maui and THIS breaks things. Beyond annoyed. I struggle not to be insulting here.

blmiles avatar Oct 08 '23 17:10 blmiles

What a useful library for Maui Apps and this Image caching debacle: https://github.com/Redth/FFImageLoading.Compat Hope that helps a few here!!

Install the nuget package the add this to the MauiProgram.cs:

.UseFFImageLoading() Add this to the xaml page where you might have you Image control(s):

xmlns:ffimageloading="clr-namespace:FFImageLoading.Maui;assembly=FFImageLoading.Compat.Maui"

Substitute the Image xaml for this:

          <ffimageloading:CachedImage CacheType="None" Source="{Binding ImagePath}" Aspect="AspectFit">
              <ffimageloading:CachedImage.HeightRequest>
                  <OnIdiom x:TypeArguments="x:Double" Phone="200" Tablet="375"  />
              </ffimageloading:CachedImage.HeightRequest>                                    
          </ffimageloading:CachedImage>

Amend to suit you reqs...

blmiles avatar Oct 10 '23 00:10 blmiles

Bump, really need this as a workaround using Image streams is not ideal.

iamlawrencev avatar Nov 29 '23 04:11 iamlawrencev

Looks like we have #13111 already merged. Does that look like it would cover this case as well?

is not fixed yet, saving images to disk with the same filename but different content serves the old file.

Eves101 avatar Dec 19 '23 12:12 Eves101

This is still not fixed, I am loading a file editing it and resaving it, It is still serving the original File.

RoyM33-T avatar Jan 19 '24 17:01 RoyM33-T

I have the same issue. The ability to set Caching properties for all ImageSources would be much appreciated! 👍

SirJohnK avatar Feb 08 '24 18:02 SirJohnK

We've having the same issue.

There is no clear official API about caching Images and this is involving such a large part of our current Xamarin app if we want to port them over to MAUI!

And for now, we can't use FFImageCompat since it has so many issues and not maintained by anybody. Such fundamental features like this is extremely important for a modern nowadays app.

unamed000 avatar Feb 10 '24 08:02 unamed000