More on #UWPCommunityToolkit CacheBase #uwpdev

In the first version of UWP Community Toolkit, we only had ImageCache which had its origin in Windows App Studio. A few issues were raised to optimise it and one mentioned extensible cache that can be used to create any case.

FileCache, ImageCache, VideoCache, JsonCache.. you name it.. Yesterday I mentioned CacheBase. FileCache and ImageCache that ship with UWP Community Toolkit are implementations of CacheBase by giving it a specific type.

Today I had to implement ability to pull configuration settings from our server. I tried using current prod version of FileCache but my implementation was somewhat wrong there. It would try to create File from Stream and return null and then fail internally (fixed in current dev branch) however I needed something today. Enter ConfigCache.. well JsonCache really

public class ConfigCache : CacheBase<ConfigurationSetting>
{
    JsonSerializer jsonSerializer = new JsonSerializer();

    /// <summary>
    /// Private singleton field.
    /// </summary>
    private static ConfigCache _instance;

    /// <summary>
    /// Gets public singleton property.
    /// </summary>
    public static ConfigCache Instance => _instance ?? (_instance = new ConfigCache() { MaintainContext = false });

    protected override async Task<ConfigurationSetting> InitializeTypeAsync(StorageFile baseFile)
    {
        using (var stream = await baseFile.OpenStreamForReadAsync())
        {
            return InitializeTypeAsync(stream);
        }
    }

    protected override Task<ConfigurationSetting> InitializeTypeAsync(IRandomAccessStream stream)
    {
        var config = InitializeTypeAsync(stream.AsStream());
        return Task.FromResult<ConfigurationSetting>(config);
    }

    private ConfigurationSetting InitializeTypeAsync(Stream stream)
    {
        var reader = new StreamReader(stream);

        using (var jsonReader = new JsonTextReader(reader))
        {
            return jsonSerializer.Deserialize<ConfigurationSetting>(jsonReader);
        }
    }
}

In this case I am using a specific type to deserialise json to. How do I use it ?

ConfigCache.Instance.CacheDuration = TimeSpan.FromDays(1);

this.ConfigurationSettings = await ConfigCache.Instance.GetFromCacheAsync(new Uri(urlPath));

This would ensure that if configuration is older than a day, it will be downloaded again. Either way the caller will get deserialised data.

VideoCache #uwp #uwpdev

Earlier today (10 mins ago), we were discussing looping animated previews (rolling video frames) for articles and that maybe we should create a cache to prevent it being downloaded over and over again.

Back in UWP Community Toolkit, we created a CacheBase – a generic base implementation of Cache. This can be used to create just about any type of data cache.

This CacheBase was then used to implement ImageCache and finally FileCache just to show it can be done with other types too. So this is what I did.

public class VideoCache : CacheBase<MediaSource>
{
    /// <summary>
    /// Private singleton field.
    /// </summary>
    private static VideoCache _instance;

    /// <summary>
    /// Gets public singleton property.
    /// </summary>
    public static VideoCache Instance => _instance ?? (_instance = new VideoCache() { MaintainContext = true });

    protected override Task<MediaSource> InitializeTypeAsync(StorageFile baseFile)
    {
        return Task.Run(() => MediaSource.CreateFromStorageFile(baseFile));
    }

    protected override Task<MediaSource> InitializeTypeAsync(IRandomAccessStream stream)
    {
        return Task.Run(() => MediaSource.CreateFromStream(stream, "video/mp4"));
    }
}

Previously in my video player (see my previous blog post), I created a MediaSource from Uri.. now this to use the Cache

//MediaSource mediaSource = MediaSource.CreateFromUri(this.Video.Uri);
MediaSource mediaSource = await VideoCache.Instance.GetFromCacheAsync(this.Video.Uri);

Now the animated previews are not only cached and reused but they are also available offline.

To ensure that you do not build a large set, always make sure you set CacheDuration and remove expired items.

// somewhere in your App.xaml.cs
VideoCache.Instance.CacheDuration = TimeSpan.FromDays(1);

elsewhere in your cleanup code

await VideoCache.Instance.RemoveExpiredAsync();

Took me about 2 mins to roll out and get it running.