Ffimageloading: Xamarin.Forms Android InvalidateCacheEntryAsync doesn't completely remove.

Created on 5 Dec 2018  路  5Comments  路  Source: luberda-molinet/FFImageLoading

Xamarin.Forms Android InvalidateCacheEntryAsync can't completely remove individual cache with CacheKeyFactory.

Description

On Android with Xamarin.Forms, when using StreamImageSource for CachedImage.Source and setting CacheKeyFactory, InvalidateCacheEntryAsync method can't completely remove individual cache.

On iOS, it can be removed and display the new image.

I use SQLite DB to manage images for my app and the record id is used as the cache key. And then I use the same key after removing the cache when an image is updated.
But the previous image will soon revive and display it.

Steps to Reproduce

  1. Put a CachedImage specified CacheKeyFactory.
  2. Specify a StreamImageSource as the source.
  3. Execute InvalidateCacheEntryAsync(the key, All, true)
  4. Update the ImageSource.Source to the other source with the same key as previous.
  5. The new image will be reflected on CachedImage.
  6. Update it again.
  7. The previous image will be displayed.

Expected Behavior

Once InvalidateCacheEntryAsync method executes, the cache will be removed and the new image will be reflected when CahcedImage.Source is updated.

Actual Behavior

Each time InvalidateCacheEntryAsync method executes and the source is updated, either the previous image will revive or the new image will be reflected.

Basic Information

  • Version with issue: 2.4.4.859
  • Last known good version: none
  • Platform: Xamarin.Forms 3.4.0.1008975 / Android

Screenshots

  1. Initial state.

  2. Tap Update.

  3. Tap Update again.

Reproduction Link / Code

The Reproduction Project

Work Around

It removes the entry also from the cache of the reuse_pool.

public class ImageServiceEx:IImageServiceEx
{
    static ByteBoundStrongLruCache<SelfDisposingBitmapDrawable> _reusePool;
    static ByteBoundStrongLruCache<SelfDisposingBitmapDrawable> ReusePool
    {
        get
        {
            if (_reusePool != null)
                return _reusePool;

            var imageCache = ImageCache.Instance as ImageCache<SelfDisposingBitmapDrawable>;
            var fieldInfo = imageCache.GetType().GetField("_cache", BindingFlags.Instance | BindingFlags.NonPublic);
            var innerCache = (ReuseBitmapDrawableCache<SelfDisposingBitmapDrawable>)fieldInfo.GetValue(imageCache);
            fieldInfo = innerCache.GetType().GetField("reuse_pool", BindingFlags.Instance | BindingFlags.NonPublic);
            _reusePool = (ByteBoundStrongLruCache<SelfDisposingBitmapDrawable>)fieldInfo.GetValue(innerCache);

            return _reusePool;
        }
    }

    public async Task ForceInvalidateCacheEntryAsync(string key, CacheType cacheType, bool removeSimilar = false)
    {
        await ImageService.Instance.InvalidateCacheEntryAsync(key, cacheType, removeSimilar);
        ReusePool.Remove(key);
    }
}

Related link

965

Most helpful comment

Fixed. Thanks @GZidar 馃憤

All 5 comments

See also #1127

Happening on Android (not forms) also. The workaround is to remove the image from the ImageViewAsync before invalidating / changing FF cache.

Workaround: imageView.SetImageDrawable(null);

Usecase:

  1. List with images on each item
  2. Tapping the item opens a new view to change the image. In that new view, invalidate cache and add new image to the saving queue
  3. Going back to the previous view, the new image should appear in that specific item.

I have created a PR with the change we made to the package that resolved this issue for us.

https://github.com/luberda-molinet/FFImageLoading/pull/1213

@GZidar
Thanks!

Fixed. Thanks @GZidar 馃憤

Was this page helpful?
0 / 5 - 0 ratings