Windowscommunitytoolkit: ImageCache to save the image directly while downloading

Created on 21 Aug 2016  路  20Comments  路  Source: windows-toolkit/WindowsCommunityToolkit

Hi guys,

First i want to thank you for this Toolkit, it looks really polished and well done. Now to my question regarding ImageCache. the title may be missleading but i dont know how to clarify my suggestion/feature for ImageCache a different way.

I currently download some RSS, parse it, and update a ObservableCollection of type FeaturedList. Its just 5 RSS items that also have pictures. ImageCache does its job but please have a look at my snippet

        XmlSerializer serializer = new XmlSerializer(typeof(rss));
        XDocument document = XDocument.Parse(FeaturedXML);
        rss RSS = (rss)serializer.Deserialize(document.CreateReader());

        foreach(var item in RSS.channel.item.ToList().Take(5))
        {
            var FeaturedImage = await ImageCache.GetFromCacheAsync(new Uri(item.thumbnail.url));
            ImageCache.CacheDuration = TimeSpan.FromDays(14);
            item.thumbnail.url = FeaturedImage.UriSource.OriginalString;
        }

        VM.FeaturedList = new ObservableCollection<rssChannelItem>(RSS.channel.item.ToList().Take(5));

This is in the method where i update the Collection. The problem is, i dont want the ImageCache download to be here, it takes up to 5 seconds per saved image *x makes 25 seconds in good conditions to get to my ObservableCollection. I would like to suggest麓a "placeholder" for each file that i add here but the saving should be on the thread where the app downloads the images without ImageCache, if you understand me. So that it is not visible that ImageCache is taking up time downloading the images and saving them. Currently i get the ObservableCollection with only image urls that are then downloaded after the collection has been called.

Is there a way to intercept the initial download of the images and place there ImageCache to save them directly to the temp folder because that would be the fastest way in my opinion.

The problem is that the items a empty until all pictures are downloaded, i like to display their titles while the images download and save to cache.

I hope there is a better solution then mine above.

controls feature help wanted

All 20 comments

Have you considered using the ImageEx control to display your images? It uses ImageCache internally and provides a placeholder.

@andrejt how does it cache the pictures? I could have a look into the control because i currently have another image as placeholder below the web based image. And i have tried now to make my snipper different but its still is a 2x work. I wish we could cache while downloading directly, the image while displayed, even from web is somewhere in the memory, i thought this ImageCache could save this file somehow so i can use it in my ObservableCollection.

but thanks will try out the ImageEx control. Is it heavier on RAM or CPU with lets say 25-50 pictures displayed then "normal" images?!

Its me again, i have tested ImageEx and it does what i wanted with the ImageCache :D it has also some nice fading animation. The ImageEx control also saved the images in the same temp folder like ImageCache. great. And can i use the ImageCache.Clear function then to clear the images of ImageEx cache?

ImageEx uses ImageCache's GetFromCacheAsync, the one you've already tried. What it does is it looks in cache if it's already there. If it's not, it downloads and caches it (saves it as a local file). In both cases the method then returns a cached image. Meaning you get the image as soon it is fully downloaded and saved into file system. In the end, you don't care where the image came from (the web or cache) - although getting it from web will take longer, of course - that's why placeholder is there.

It's not heavy really, it's something you'd do anyway if not using a dedicated control. It's using some storyboards to fade from placeholder to actual image which may get replaced with Composition animations at some point in the future.

@Dinchy87 Yes, you can use the Clear method, it's the same cache.

Thanks, its a great control, playing with it now. But can i spam this thread with one more question? regarding ImageEx. The placeholder image, is there any control over it i mean over its opacity? i would like to set a placeholder that has a opacity like 0.15 or 0.2 which would look really good for my solution.

And if the cache is not deleted manually how long will ImageEx hold older pictures?

@dinchy87 just retemplate the control.

@ScottIsAFool Yeah, or i add a new placeholder that has already the opacity i need. Thanks guys. I love already the whole Uwp Toolkit :)

@Dinchy87 default cache expiration is set to 24 hours, you can change it with CacheDuration property (which you've already found) - enough to set it once, because it affects all gets from cache.

The files themselves, well they'll stay there 'forever' if you don't delete them (they are stored in LocalFolder).

Great. Thanks a lot.

The files themselves, well they'll stay there 'forever' if you don't delete them.

What does this exactly mean, @andrejt? When cache is cleared, aren't the files deleted? If the app doesn't delete files, does it mean that users will see the app size grow over time?

@akshay2000 Yes, you have to explicitly call ClearAsync method to delete old files, otherwise it will stay there and fill up your space. You can call it on app start or when you're sure you won't need stored images anymore. That said, I'm using TemporaryFolder in my apps and can't say why LocalFolder was chosen for this implementation.

@andrejt maybe a change to TemporaryFolder would be a better approach then? Perhaps submit a PR?

@ScottIsAFool well, I was thinking of taking it a bit further:

  1. Decouple "ImageCache" from "File" cache implementation, e.g. have FileCache class as a base caching service and ImageCacheService for image-related interactions over the cache. That way, the FileCache can be used in other caching scenarios, using e.g. JsonCacheService, XmlCacheService, etc.
  2. Define a IImageCache interface and declare it as a property on ImageCacheEx so anyone could plug in their own caching provider. eg.
<ImageEx Property="value" ... ...>
    <ImageEx.CachingService>
        <local:MyImageCachingService Root="ms-appdata:///temp/" />
    </ImageEx.CachingService>
</ImageEx>
  1. In addition to FileCacheService, provide MemoryCacheService (in-memory, lasts only for the duration of the app running)

Anyway, something I was using for a while now & working on to include it in the toolkit. I'll submit a PR when ready.

@ScottIsAFool Yes. It will keep the app size from growing. It will also auto handle clearing out of temporary files.
@andrejt While I like the idea, I am afraid this makes it unnecessarily complicated. On the other hand, having more options to cache files seems even better. As long as the toolkit ships with a default implementation of IImageCache we should be good to go. We could even set ImageEx.CachingService to default implementation so that there's no extra XAML. This will also prevent existing usage from breaking.

@akshay2000 of course, the plan was that default implementation would stay as is now and would be the one used if not overriden by the property. Flexible, but working out of the box if you like the default cache implementation.

This is a really good idea! Let us know if you need help:)

i have started working on FileCache and I will built the ImageCache on that once its working well

i hve done some work on modifying cache and having a common base class. Can I please have some feedback on this ?
https://github.com/Microsoft/UWPCommunityToolkit/tree/hd-cache-rework/Microsoft.Toolkit.Uwp.UI/Cache

I'm starting with decoupling of file caching from images caching. As @andrejt mentioned. I'm however not doing pluggable caching mechanism.. Just separate and something we cash build other caching services on

Was this page helpful?
0 / 5 - 0 ratings