From 7fca0e9be930e44d5e3a084e853a4b850aadb274 Mon Sep 17 00:00:00 2001 From: Dmitry Vakhnin Date: Mon, 31 Jul 2023 01:50:07 +0200 Subject: [PATCH 1/2] Added getImageFileFromCache --- .gitignore | 2 + .../cache_managers/image_cache_manager.dart | 34 +++++++++++ .../test/image_cache_manager_test.dart | 60 ++++++++++++++++++- 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 856e7441..556b6c26 100644 --- a/.gitignore +++ b/.gitignore @@ -94,3 +94,5 @@ flutter_export_environment.sh !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages example/.flutter-plugins-dependencies flutter_cache_manager/example/ios/Flutter/.last_build_id + +flutter_cache_manager/coverage/ diff --git a/flutter_cache_manager/lib/src/cache_managers/image_cache_manager.dart b/flutter_cache_manager/lib/src/cache_managers/image_cache_manager.dart index 614d7d9d..f6c65dd7 100644 --- a/flutter_cache_manager/lib/src/cache_managers/image_cache_manager.dart +++ b/flutter_cache_manager/lib/src/cache_managers/image_cache_manager.dart @@ -7,7 +7,41 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; const supportedFileNames = ['jpg', 'jpeg', 'png', 'tga', 'cur', 'ico']; + mixin ImageCacheManager on BaseCacheManager { + /// Get the image from the cache and resize if needed + /// Specify [ignoreMemCache] to force a re-read from the database + Future getImageFileFromCache( + String key, { + int? maxHeight, + int? maxWidth, + bool ignoreMemCache = false, + }) async { + final fromCache = + await getFileFromCache(key, ignoreMemCache: ignoreMemCache); + if ((maxHeight == null && maxWidth == null) || fromCache == null) { + return fromCache; + } + + var resizedKey = 'resized'; + if (maxWidth != null) resizedKey += '_w$maxWidth'; + if (maxHeight != null) resizedKey += '_h$maxHeight'; + resizedKey += '_$key'; + + final fromCacheResized = + await getFileFromCache(resizedKey, ignoreMemCache: ignoreMemCache); + if (fromCacheResized != null) { + return fromCacheResized; + } + final resizedFile = await _resizeImageFile( + fromCache, + resizedKey, + maxWidth, + maxHeight, + ); + return resizedFile; + } + /// Returns a resized image file to fit within maxHeight and maxWidth. It /// tries to keep the aspect ratio. It stores the resized image by adding /// the size to the key or url. For example when resizing diff --git a/flutter_cache_manager/test/image_cache_manager_test.dart b/flutter_cache_manager/test/image_cache_manager_test.dart index f3701d5d..0076a70d 100644 --- a/flutter_cache_manager/test/image_cache_manager_test.dart +++ b/flutter_cache_manager/test/image_cache_manager_test.dart @@ -125,6 +125,59 @@ void main() { expect(progress, isNotEmpty); }); }); + group('Test resized image getting from cache', () { + test('Image should be fetched from cache without resizing', () async { + var config = await setupConfig(cacheKey: fileName); + var cacheManager = TestCacheManager(config); + var result = await cacheManager.getImageFileFromCache( + fileName, + ) as FileInfo?; + + await verifySize(result?.file.readAsBytesSync(), 120, 120); + config.verifyNoDownloadCall(); + }); + + test('Image should be fetched from cache with resizing', () async { + var config = await setupConfig(cacheKey: fileName); + var cacheManager = TestCacheManager(config); + var result = await cacheManager.getImageFileFromCache( + fileName, + maxHeight: 100, + maxWidth: 80, + ) as FileInfo?; + + await verifySize(result?.file.readAsBytesSync(), 80, 80); + config.verifyNoDownloadCall(); + }); + + test('Resized image should be fetched from cache', () async { + var config = await setupConfig(cacheKey: fileName); + config.returnsCacheObject(fileUrl, fileName, validTill, + key: 'resized_w100_h80_$fileName'); + var cacheManager = TestCacheManager(config); + var result = await cacheManager.getImageFileFromCache( + fileName, + maxWidth: 100, + maxHeight: 80, + ) as FileInfo?; + + expect(result, isNotNull); + config.verifyNoDownloadCall(); + }); + + test('If no image is in cache null should be returned', () async { + var config = await setupConfig(cacheKey: ''); + var cacheManager = TestCacheManager(config); + var result = await cacheManager.getImageFileFromCache( + fileUrl, + maxWidth: 100, + maxHeight: 80, + ) as FileInfo?; + + expect(result, isNull); + config.verifyNoDownloadCall(); + }); + }); } Future setupCacheManager() async { @@ -140,10 +193,15 @@ Future setupConfig({String? cacheKey}) async { } Future verifySize( - Uint8List image, + Uint8List? image, int expectedWidth, int expectedHeight, ) async { + expect(image, isNotNull); + if (image == null) { + return; + } + var codec = await instantiateImageCodec(image); var frame = await codec.getNextFrame(); var height = frame.image.height; From dd72dd9b8019575ff1f0cb8e7d3843a5a1678a51 Mon Sep 17 00:00:00 2001 From: Dmitry Vakhnin Date: Mon, 31 Jul 2023 02:24:05 +0200 Subject: [PATCH 2/2] Updated readme, added getFileFromCache description --- flutter_cache_manager/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flutter_cache_manager/README.md b/flutter_cache_manager/README.md index 8ea4e19e..fac7d22e 100644 --- a/flutter_cache_manager/README.md +++ b/flutter_cache_manager/README.md @@ -56,6 +56,9 @@ The image from the url is resized within the specifications, and the resized ima always tries to keep the existing aspect ratios. The original image is also cached and used to resize the image if you call this method with other height/width parameters. +And also there's a `getFileFromCache` method that returns a resized image from the cache only without downloading it. +`getFileFromCache` only retrieves from cache and returns no image when the image is not in the cache. + ## Other implementations When your files are stored on Firebase Storage you can use [flutter_cache_manager_firebase](https://pub.dev/packages/flutter_cache_manager_firebase).