From bb30ed04e33d608a284677930d76ed274efa8996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Sallai?= Date: Sun, 30 May 2021 16:04:54 +0300 Subject: [PATCH 1/2] update dependencies and add nullsafety support --- example/.flutter-plugins-dependencies | 2 +- example/android/app/build.gradle | 4 ++-- example/android/gradlew | 0 example/pubspec.yaml | 4 ++++ .../flutter_advanced_networkimage.dart | 20 +++++++++++++++---- .../provider/flutter_advanced_networksvg.dart | 2 +- lib/src/utils.dart | 3 ++- pubspec.yaml | 16 +++++++-------- test/download_test.dart | 12 +++++------ 9 files changed, 40 insertions(+), 23 deletions(-) mode change 100644 => 100755 example/android/gradlew diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies index 8cd7e6d..6d67d53 100644 --- a/example/.flutter-plugins-dependencies +++ b/example/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider","path":"/Users/lifenautjoe/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.11/","dependencies":[]}],"android":[{"name":"path_provider","path":"/Users/lifenautjoe/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.11/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lifenautjoe/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+3/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lifenautjoe/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/","dependencies":[]}],"windows":[],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]}],"date_created":"2020-08-18 21:11:09.495432","version":"1.21.0-10.0.pre.129"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/","dependencies":[]}],"android":[{"name":"path_provider","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-2.0.0/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-2.0.0/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-2.0.1/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2021-05-30 16:00:03.503548","version":"2.0.6"} \ No newline at end of file diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index f48bfd1..755ef0e 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -15,7 +15,7 @@ apply plugin: 'com.android.application' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 27 + compileSdkVersion 29 lintOptions { disable 'InvalidPackage' @@ -25,7 +25,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.flutteradvancednetworkimageexample" minSdkVersion 16 - targetSdkVersion 27 + targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/example/android/gradlew b/example/android/gradlew old mode 100644 new mode 100755 diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 53de07b..293da61 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -9,3 +9,7 @@ dependencies: flutter: uses-material-design: true + +environment: + sdk: ">=2.10.0 <3.0.0" + flutter: ">=2.0.0 <3.0.0" diff --git a/lib/src/provider/flutter_advanced_networkimage.dart b/lib/src/provider/flutter_advanced_networkimage.dart index be99429..b46c2a3 100644 --- a/lib/src/provider/flutter_advanced_networkimage.dart +++ b/lib/src/provider/flutter_advanced_networkimage.dart @@ -125,13 +125,16 @@ class AdvancedNetworkImage extends ImageProvider { ImageStream resolve(ImageConfiguration configuration) { assert(configuration != null); final ImageStream stream = ImageStream(); - obtainKey(configuration).then((AdvancedNetworkImage key) { + obtainKey(configuration).then((AdvancedNetworkImage key) async { if (key.disableMemoryCache) { - stream.setCompleter(load(key)); + stream.setCompleter(load(key, _decoderCallback)); + } + if (key.disableMemoryCache) { + stream.setCompleter(load(key, _decoderCallback)); } else { final ImageStreamCompleter completer = PaintingBinding .instance.imageCache - .putIfAbsent(key, () => load(key)); + .putIfAbsent(key, () => load(key, _decoderCallback)); if (completer != null) stream.setCompleter(completer); } }); @@ -144,7 +147,7 @@ class AdvancedNetworkImage extends ImageProvider { } @override - ImageStreamCompleter load(AdvancedNetworkImage key) { + ImageStreamCompleter load(AdvancedNetworkImage key, DecoderCallback callback) { return MultiFrameImageStreamCompleter( codec: _loadAsync(key), scale: key.scale, @@ -155,6 +158,15 @@ class AdvancedNetworkImage extends ImageProvider { ); } + Future _decoderCallback(Uint8List bytes) { + // We're not actually using this, but Flutter requires this as a callback. + // Since we're loading the image asynchronously and the `load` method can't + // be asynchronous, we will pass _loadAsync directly to the codec property + // instad of using the callback. + + return PaintingBinding.instance.instantiateImageCodec(bytes); + } + Future _loadAsync(AdvancedNetworkImage key) async { assert(key == this); diff --git a/lib/src/provider/flutter_advanced_networksvg.dart b/lib/src/provider/flutter_advanced_networksvg.dart index a2ef844..3848254 100644 --- a/lib/src/provider/flutter_advanced_networksvg.dart +++ b/lib/src/provider/flutter_advanced_networksvg.dart @@ -39,7 +39,7 @@ class AdvancedNetworkSvg extends PictureProvider { assert(useDiskCache != null), assert(retryLimit != null), assert(retryDuration != null), - assert(printError != null); + assert(printError != null), super(null); /// The URL from which the image will be fetched. final String url; diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 758a910..97e6a4a 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -384,7 +384,8 @@ Future loadFromRemote( return completer.future; } else { - return await http.get(_url, headers: header).timeout(timeoutDuration); + Uri uri = Uri.parse(_url); + return await http.get(uri, headers: header).timeout(timeoutDuration); } }, retryLimit, retryDuration, retryDurationFactor); if (_response != null) return _response.bodyBytes; diff --git a/pubspec.yaml b/pubspec.yaml index e145922..21867a3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,22 +1,22 @@ name: flutter_advanced_networkimage description: An advanced image provider provides caching and retrying for flutter app. Now with zoomable widget and transition to image widget. -version: 0.6.0 +version: 0.7.0 author: "fuyumi " homepage: https://github.com/mchome/flutter_advanced_networkimage dependencies: flutter: sdk: flutter - http: ^0.12.2 - path_provider: ^1.6.11 - path: ^1.7.0 - flutter_svg: ^0.18.0 + http: ^0.13.3 + path_provider: ^2.0.2 + path: ^1.8.0 + flutter_svg: ^0.22.0 dev_dependencies: flutter_test: sdk: flutter - test: "^1.6.0" + test: any environment: - sdk: ">=2.3.0 <3.0.0" - flutter: ">=1.8.0 <2.0.0" + sdk: ">=2.10.0 <3.0.0" + flutter: ">=2.0.0 <3.0.0" diff --git a/test/download_test.dart b/test/download_test.dart index abdb217..3246ec5 100644 --- a/test/download_test.dart +++ b/test/download_test.dart @@ -9,7 +9,7 @@ void main() { group('Download Test', () { test('=> good url', () async { var url = 'https://flutter.dev/images/flutter-logo-sharing.png'; - var result = (await http.get(url)).bodyBytes; + var result = (await http.get(Uri.parse(url))).bodyBytes; expect( await loadFromRemote(url, null, 5, const Duration(milliseconds: 100), @@ -18,8 +18,8 @@ void main() { result); url = - 'https://flutter.dev/assets/flutter-lockup-4cb0ee072ab312e59784d9fbf4fb7ad42688a7fdaea1270ccf6bbf4f34b7e03f.svg'; - result = (await http.get(url)).bodyBytes; + 'https://flutter.dev/images/flutter-mono-81x100.png'; + result = (await http.get(Uri.parse(url))).bodyBytes; expect( await loadFromRemote(url, null, 5, const Duration(milliseconds: 100), @@ -30,7 +30,7 @@ void main() { test('=> good url with progress', () async { var url = 'this is a label'; var realUrl = 'https://flutter.dev/images/flutter-logo-sharing.png'; - var result = (await http.get(realUrl)).bodyBytes; + var result = (await http.get(Uri.parse(realUrl))).bodyBytes; expect( await loadFromRemote( @@ -48,8 +48,8 @@ void main() { url = 'this is another label'; realUrl = - 'https://flutter.dev/assets/flutter-lockup-4cb0ee072ab312e59784d9fbf4fb7ad42688a7fdaea1270ccf6bbf4f34b7e03f.svg'; - result = (await http.get(realUrl)).bodyBytes; + 'https://flutter.dev/images/flutter-mono-81x100.png'; + result = (await http.get(Uri.parse(realUrl))).bodyBytes; expect( await loadFromRemote( From 0b2c9775f8ab375c47f812a459f276b9feb107b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Sallai?= Date: Fri, 25 Jun 2021 23:32:35 +0300 Subject: [PATCH 2/2] better nullsafety migration --- example/.flutter-plugins-dependencies | 2 +- example/lib/main.dart | 14 +- example/pubspec.yaml | 2 +- lib/src/cropper/image_cropper.dart | 52 +++---- lib/src/disk_cache.dart | 59 ++++---- .../flutter_advanced_networkimage.dart | 80 ++++++----- .../provider/flutter_advanced_networksvg.dart | 52 +++---- lib/src/transition/raw_image.dart | 135 +++++++++--------- lib/src/transition/transition_to_image.dart | 70 ++++----- lib/src/utils.dart | 26 ++-- lib/src/zoomable/zoomable_list.dart | 34 ++--- lib/src/zoomable/zoomable_widget.dart | 58 ++++---- pubspec.yaml | 2 +- test/cache_test.dart | 87 +++++------ 14 files changed, 344 insertions(+), 329 deletions(-) diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies index 6d67d53..1b96bf4 100644 --- a/example/.flutter-plugins-dependencies +++ b/example/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/","dependencies":[]}],"android":[{"name":"path_provider","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-2.0.0/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-2.0.0/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-2.0.1/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2021-05-30 16:00:03.503548","version":"2.0.6"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/","dependencies":[]}],"android":[{"name":"path_provider","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-2.0.0/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-2.0.0/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/home/joe/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-2.0.1/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2021-06-25 23:29:50.493168","version":"2.0.6"} \ No newline at end of file diff --git a/example/lib/main.dart b/example/lib/main.dart index cdc9ac2..37d8aab 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -59,7 +59,7 @@ class Example extends State { } class LoadImage extends StatelessWidget { - const LoadImage({@required this.url, @required this.svgUrl}); + const LoadImage({required this.url, required this.svgUrl}); final String url; final String svgUrl; @@ -95,7 +95,7 @@ class LoadImage extends StatelessWidget { loadingWidgetBuilder: ( BuildContext context, double progress, - Uint8List imageData, + Uint8List? imageData, ) { // print(imageData.lengthInBytes); return Container( @@ -122,7 +122,7 @@ class LoadImage extends StatelessWidget { } class ZoomableImage extends StatelessWidget { - const ZoomableImage({@required this.url}); + const ZoomableImage({required this.url}); final String url; @@ -140,7 +140,7 @@ class ZoomableImage extends StatelessWidget { } class ZoomableImages extends StatelessWidget { - const ZoomableImages({@required this.url}); + const ZoomableImages({required this.url}); final String url; @@ -163,7 +163,7 @@ class ZoomableImages extends StatelessWidget { } class CropImage extends StatefulWidget { - const CropImage({@required this.url}); + const CropImage({required this.url}); final String url; @@ -172,7 +172,7 @@ class CropImage extends StatefulWidget { } class _CropImageState extends State { - Uint8List imageCropperData; + Uint8List? imageCropperData; void cropImage(Uint8List data) => setState(() => imageCropperData = data); @@ -209,7 +209,7 @@ class _CropImageState extends State { content: SingleChildScrollView( child: Container( child: imageCropperData != null - ? Image.memory(imageCropperData) + ? Image.memory(imageCropperData!) : Container(), ), ), diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 293da61..5a72aa9 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -11,5 +11,5 @@ flutter: uses-material-design: true environment: - sdk: ">=2.10.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" flutter: ">=2.0.0 <3.0.0" diff --git a/lib/src/cropper/image_cropper.dart b/lib/src/cropper/image_cropper.dart index e4bb3ef..c7bcac0 100644 --- a/lib/src/cropper/image_cropper.dart +++ b/lib/src/cropper/image_cropper.dart @@ -9,11 +9,11 @@ import 'package:flutter_advanced_networkimage/src/utils.dart'; class ImageCropper extends StatefulWidget { ImageCropper({ - Key key, - @required this.child, + Key? key, + required this.child, this.minScale: 1.0, this.maxScale: 3.0, - @required this.onCropperChanged, + required this.onCropperChanged, }); final Widget child; @@ -44,8 +44,8 @@ class _ImageCropperState extends State { Curve _curve = Curves.easeOut; void _onScaleStart(ScaleStartDetails details) { - if (_childSize == Size.zero) { - final RenderBox renderbox = _key.currentContext.findRenderObject(); + if (_childSize == Size.zero && _key.currentContext != null) { + final RenderBox renderbox = _key.currentContext!.findRenderObject() as RenderBox; _childSize = renderbox.size; } setState(() { @@ -142,12 +142,12 @@ class _ImageCropperState extends State { class _AnimatedCropper extends ImplicitlyAnimatedWidget { const _AnimatedCropper({ - Duration duration, + required Duration duration, Curve curve = Curves.linear, - @required this.zoom, - @required this.panOffset, - @required this.rotation, - @required this.child, + required this.zoom, + required this.panOffset, + required this.rotation, + required this.child, }) : super(duration: duration, curve: curve); final double zoom; @@ -161,33 +161,37 @@ class _AnimatedCropper extends ImplicitlyAnimatedWidget { } class _AnimatedCropperState extends AnimatedWidgetBaseState<_AnimatedCropper> { - DoubleTween _zoom; - OffsetTween _panOffset; - OffsetTween _zoomOriginOffset; - DoubleTween _rotation; + DoubleTween? _zoom; + OffsetTween? _panOffset; + OffsetTween? _zoomOriginOffset; + DoubleTween? _rotation; @override void forEachTween(visitor) { _zoom = visitor( - _zoom, widget.zoom, (dynamic value) => DoubleTween(begin: value)); + _zoom, widget.zoom, (dynamic value) => DoubleTween(begin: value)) as DoubleTween; _panOffset = visitor(_panOffset, widget.panOffset, - (dynamic value) => OffsetTween(begin: value)); + (dynamic value) => OffsetTween(begin: value)) as OffsetTween; _rotation = visitor(_rotation, widget.rotation, - (dynamic value) => DoubleTween(begin: value)); + (dynamic value) => DoubleTween(begin: value)) as DoubleTween; } @override Widget build(BuildContext context) { return Transform( alignment: Alignment.center, - origin: Offset(-_panOffset.evaluate(animation).dx, - -_panOffset.evaluate(animation).dy), - transform: Matrix4.identity() - ..translate(_panOffset.evaluate(animation).dx, - _panOffset.evaluate(animation).dy) - ..scale(_zoom.evaluate(animation), _zoom.evaluate(animation)), + origin: _panOffset == null + ? Offset(0, 0) + : Offset(-_panOffset!.evaluate(animation).dx, + -_panOffset!.evaluate(animation).dy), + transform: _panOffset == null || _zoom == null + ? Matrix4.identity() + : Matrix4.identity() + ..translate(_panOffset!.evaluate(animation).dx, + _panOffset!.evaluate(animation).dy) + ..scale(_zoom!.evaluate(animation), _zoom!.evaluate(animation)), child: Transform.rotate( - angle: _rotation.evaluate(animation), + angle: _rotation?.evaluate(animation) ?? 0, child: widget.child, ), ); diff --git a/lib/src/disk_cache.dart b/lib/src/disk_cache.dart index 6426cb2..e048f6f 100644 --- a/lib/src/disk_cache.dart +++ b/lib/src/disk_cache.dart @@ -72,14 +72,14 @@ class DiskCache { int _currentOps = 0; - int get currentEntries => _metadata != null ? _metadata.keys.length : 0; + int get currentEntries => _metadata != null ? _metadata!.keys.length : 0; int get _currentSizeBytes { int size = 0; - _metadata.values.forEach((item) => size += item['size']); + _metadata?.values.forEach((item) => size += item['size'] as int); return size; } - Map _metadata; + Map? _metadata; static const String _metadataFilename = 'imagecache_metadata.json'; @@ -112,7 +112,7 @@ class DiskCache { /// Clean up the bad cache files in metadata. Future keepCacheHealth() async { if (_metadata == null) await _initMetaData(); - _metadata.removeWhere((k, v) { + _metadata!.removeWhere((k, v) { if (!File(v['path']).existsSync()) return true; if (DateTime.fromMillisecondsSinceEpoch(v['createdTime'] + v['maxAge']) .isBefore(DateTime.now())) { @@ -131,39 +131,38 @@ class DiskCache { } /// Load the cache image from [DiskCache], you can use `force` to skip max age check. - Future load(String uid, {CacheRule rule, bool force}) async { + Future load(String uid, {CacheRule? rule, bool force = false}) async { if (_metadata == null) await _initMetaData(); - force ??= false; try { - if (_metadata.containsKey(uid)) { - if (!File(_metadata[uid]['path']).existsSync()) { - _metadata.remove(uid); + if (_metadata!.containsKey(uid)) { + if (!File(_metadata![uid]['path']).existsSync()) { + _metadata!.remove(uid); await _commitMetaData(); return null; } if (DateTime.fromMillisecondsSinceEpoch( - _metadata[uid]['createdTime'] + + _metadata![uid]['createdTime'] + (rule != null ? rule.maxAge.inMilliseconds - : _metadata[uid]['maxAge']), + : _metadata![uid]['maxAge']), ).isBefore(DateTime.now()) && !force) { - await File(_metadata[uid]['path']).delete(); - _metadata.remove(uid); + await File(_metadata![uid]['path']).delete(); + _metadata!.remove(uid); await _commitMetaData(); return null; } - Uint8List data = await File(_metadata[uid]['path']).readAsBytes(); - if (_metadata[uid]['crc32'] != null && - _metadata[uid]['crc32'] != crc32(data)) { - await File(_metadata[uid]['path']).delete(); - _metadata.remove(uid); + Uint8List data = await File(_metadata![uid]['path']).readAsBytes(); + if (_metadata![uid]['crc32'] != null && + _metadata![uid]['crc32'] != crc32(data)) { + await File(_metadata![uid]['path']).delete(); + _metadata!.remove(uid); await _commitMetaData(); return null; } if (currentEntries >= maxEntries || _currentSizeBytes >= maxSizeBytes) { - _metadata[uid] = _metadata.remove(uid); + _metadata![uid] = _metadata!.remove(uid); await _commitMetaData(); } return data; @@ -197,7 +196,7 @@ class DiskCache { 'size': data.lengthInBytes, 'maxAge': rule.maxAge.inMilliseconds, }; - _metadata[uid] = metadata; + _metadata![uid] = metadata; await _checkCacheSize(); await _commitMetaData(true); @@ -209,11 +208,13 @@ class DiskCache { } Future _checkCacheSize() async { + if (_metadata == null) await _initMetaData(); + while (currentEntries > maxEntries || _currentSizeBytes > maxSizeBytes) { - String key = _metadata.keys.first; - if (File(_metadata[key]['path']).existsSync()) - await File(_metadata[key]['path']).delete(); - _metadata.remove(key); + String key = _metadata!.keys.first; + if (File(_metadata![key]['path']).existsSync()) + await File(_metadata![key]['path']).delete(); + _metadata!.remove(key); } } @@ -228,10 +229,10 @@ class DiskCache { ).path, uid)); - if (_metadata.containsKey(uid) && - File(_metadata[uid]['path']).existsSync()) { - await File(_metadata[uid]['path']).delete(); - _metadata.remove(uid); + if (_metadata!.containsKey(uid) && + File(_metadata![uid]['path']).existsSync()) { + await File(_metadata![uid]['path']).delete(); + _metadata!.remove(uid); await _commitMetaData(); } else if (normalCacheFile.existsSync()) { await normalCacheFile.delete(); @@ -264,7 +265,7 @@ class DiskCache { } /// Get cache folder size. - Future cacheSize() async { + Future cacheSize() async { int size = 0; try { Directory tempDir = diff --git a/lib/src/provider/flutter_advanced_networkimage.dart b/lib/src/provider/flutter_advanced_networkimage.dart index b46c2a3..c027a10 100644 --- a/lib/src/provider/flutter_advanced_networkimage.dart +++ b/lib/src/provider/flutter_advanced_networkimage.dart @@ -54,7 +54,7 @@ class AdvancedNetworkImage extends ImageProvider { final double scale; /// The HTTP headers that will be used with [http] to fetch image from network. - final Map header; + final Map? header; /// The flag control the disk cache will be used or not. final bool useDiskCache; @@ -72,35 +72,35 @@ class AdvancedNetworkImage extends ImageProvider { final Duration timeoutDuration; /// The callback will fire when the image loaded. - final VoidCallback loadedCallback; + final VoidCallback? loadedCallback; /// The callback will fire when the image failed to load. - final VoidCallback loadFailedCallback; + final VoidCallback? loadFailedCallback; /// The callback will fire when the image loaded from DiskCache. - VoidCallback loadedFromDiskCacheCallback; + VoidCallback? loadedFromDiskCacheCallback; /// Displays image from an asset bundle when the image failed to load. - final String fallbackAssetImage; + final String? fallbackAssetImage; /// The image will be displayed when the image failed to load /// and [fallbackAssetImage] is null. - final Uint8List fallbackImage; + final Uint8List? fallbackImage; /// Disk cache rules for advanced control. - final CacheRule cacheRule; + final CacheRule? cacheRule; /// Report loading progress and data when fetching image. - LoadingProgress loadingProgress; + LoadingProgress? loadingProgress; /// Extract the real url before fetching. - final UrlResolver getRealUrl; + final UrlResolver? getRealUrl; /// Receive the data([Uint8List]) and do some manipulations before saving. - final ImageProcessing preProcessing; + final ImageProcessing? preProcessing; /// Receive the data([Uint8List]) and do some manipulations after saving. - final ImageProcessing postProcessing; + final ImageProcessing? postProcessing; /// If set to enable, the image will skip [ImageCache]. /// @@ -120,10 +120,9 @@ class AdvancedNetworkImage extends ImageProvider { final bool printError; /// The [HttpStatus] code that you can skip retrying if you meet them. - final List skipRetryStatusCode; + final List? skipRetryStatusCode; ImageStream resolve(ImageConfiguration configuration) { - assert(configuration != null); final ImageStream stream = ImageStream(); obtainKey(configuration).then((AdvancedNetworkImage key) async { if (key.disableMemoryCache) { @@ -132,9 +131,9 @@ class AdvancedNetworkImage extends ImageProvider { if (key.disableMemoryCache) { stream.setCompleter(load(key, _decoderCallback)); } else { - final ImageStreamCompleter completer = PaintingBinding - .instance.imageCache - .putIfAbsent(key, () => load(key, _decoderCallback)); + final ImageStreamCompleter? completer = PaintingBinding + .instance?.imageCache + ?.putIfAbsent(key, () => load(key, _decoderCallback)); if (completer != null) stream.setCompleter(completer); } }); @@ -158,13 +157,13 @@ class AdvancedNetworkImage extends ImageProvider { ); } - Future _decoderCallback(Uint8List bytes) { + Future _decoderCallback(Uint8List bytes, {int? cacheWidth, int? cacheHeight, bool allowUpscaling = false}) { // We're not actually using this, but Flutter requires this as a callback. // Since we're loading the image asynchronously and the `load` method can't // be asynchronous, we will pass _loadAsync directly to the codec property // instad of using the callback. - return PaintingBinding.instance.instantiateImageCodec(bytes); + return PaintingBinding.instance!.instantiateImageCodec(bytes); } Future _loadAsync(AdvancedNetworkImage key) async { @@ -174,19 +173,19 @@ class AdvancedNetworkImage extends ImageProvider { if (useDiskCache) { try { - Uint8List _diskCache = await _loadFromDiskCache(key, uId); + Uint8List? _diskCache = await _loadFromDiskCache(key, uId); if (_diskCache != null) { if (key.postProcessing != null) - _diskCache = (await key.postProcessing(_diskCache)) ?? _diskCache; - if (key.loadedCallback != null) key.loadedCallback(); + _diskCache = (await key.postProcessing!(_diskCache)) ?? _diskCache; + if (key.loadedCallback != null) key.loadedCallback!(); return await PaintingBinding.instance - .instantiateImageCodec(_diskCache); + !.instantiateImageCodec(_diskCache); } } catch (e) { if (key.printError) debugPrint(e.toString()); } } else { - Uint8List imageData = await loadFromRemote( + Uint8List? imageData = await loadFromRemote( key.url, key.header, key.retryLimit, @@ -199,21 +198,21 @@ class AdvancedNetworkImage extends ImageProvider { ); if (imageData != null) { if (key.postProcessing != null) - imageData = (await key.postProcessing(imageData)) ?? imageData; - if (key.loadedCallback != null) key.loadedCallback(); - return await PaintingBinding.instance.instantiateImageCodec(imageData); + imageData = (await key.postProcessing!(imageData)) ?? imageData; + if (key.loadedCallback != null) key.loadedCallback!(); + return await PaintingBinding.instance!.instantiateImageCodec(imageData); } } - if (key.loadFailedCallback != null) key.loadFailedCallback(); + if (key.loadFailedCallback != null) key.loadFailedCallback!(); if (key.fallbackAssetImage != null) { - ByteData imageData = await rootBundle.load(key.fallbackAssetImage); + ByteData imageData = await rootBundle.load(key.fallbackAssetImage!); return await PaintingBinding.instance - .instantiateImageCodec(imageData.buffer.asUint8List()); + !.instantiateImageCodec(imageData.buffer.asUint8List()); } if (key.fallbackImage != null) return await PaintingBinding.instance - .instantiateImageCodec(key.fallbackImage); + !.instantiateImageCodec(key.fallbackImage!); return Future.error(StateError('Failed to load $url.')); } @@ -253,7 +252,7 @@ class AdvancedNetworkImage extends ImageProvider { /// 1. Check if cache directory exist. If not exist, create it. /// 2. Check if cached file(uid) exist. If yes, load the cache, /// otherwise go to download step. -Future _loadFromDiskCache( +Future _loadFromDiskCache( AdvancedNetworkImage key, String uId) async { if (key.cacheRule == null) { Directory _cacheImagesDirectory = @@ -262,14 +261,14 @@ Future _loadFromDiskCache( File _cacheImageFile = File(join(_cacheImagesDirectory.path, uId)); if (_cacheImageFile.existsSync()) { if (key.loadedFromDiskCacheCallback != null) - key.loadedFromDiskCacheCallback(); + key.loadedFromDiskCacheCallback!(); return await _cacheImageFile.readAsBytes(); } } else { await _cacheImagesDirectory.create(); } - Uint8List imageData = await loadFromRemote( + Uint8List? imageData = await loadFromRemote( key.url, key.header, key.retryLimit, @@ -283,17 +282,17 @@ Future _loadFromDiskCache( ); if (imageData != null) { if (key.preProcessing != null) - imageData = (await key.preProcessing(imageData)) ?? imageData; + imageData = (await key.preProcessing!(imageData)) ?? imageData; await (File(join(_cacheImagesDirectory.path, uId))) .writeAsBytes(imageData); return imageData; } } else { DiskCache diskCache = DiskCache()..printError = key.printError; - Uint8List data = await diskCache.load(uId, rule: key.cacheRule); + Uint8List? data = await diskCache.load(uId, rule: key.cacheRule); if (data != null) { if (key.loadedFromDiskCacheCallback != null) - key.loadedFromDiskCacheCallback(); + key.loadedFromDiskCacheCallback!(); return data; } @@ -310,8 +309,13 @@ Future _loadFromDiskCache( ); if (data != null) { if (key.preProcessing != null) - data = (await key.preProcessing(data)) ?? data; - await diskCache.save(uId, data, key.cacheRule); + data = (await key.preProcessing!(data)) ?? data; + + if (key.cacheRule == null) { + return null; + } + + await diskCache.save(uId, data, key.cacheRule!); return data; } } diff --git a/lib/src/provider/flutter_advanced_networksvg.dart b/lib/src/provider/flutter_advanced_networksvg.dart index 3848254..cec9800 100644 --- a/lib/src/provider/flutter_advanced_networksvg.dart +++ b/lib/src/provider/flutter_advanced_networksvg.dart @@ -51,10 +51,10 @@ class AdvancedNetworkSvg extends PictureProvider { final double scale; /// The HTTP headers that will be used with [http] to fetch image from network. - final Map header; + final Map? header; /// The [ColorFilter], if any, to apply to the drawing. - final ColorFilter colorFilter; + final ColorFilter? colorFilter; /// The flag control the disk cache will be used or not. final bool useDiskCache; @@ -72,29 +72,29 @@ class AdvancedNetworkSvg extends PictureProvider { final Duration timeoutDuration; /// The callback will be executed when the image loaded. - final Function loadedCallback; + final Function? loadedCallback; /// The callback will be executed when the image failed to load. - final Function loadFailedCallback; + final Function? loadFailedCallback; /// Displays image from an asset bundle when the image failed to load. - final String fallbackAssetImage; + final String? fallbackAssetImage; /// The image will be displayed when the image failed to load /// and [fallbackAssetImage] is null. - final Uint8List fallbackImage; + final Uint8List? fallbackImage; /// Disk cache rules for advanced control. - final CacheRule cacheRule; + final CacheRule? cacheRule; /// Extract the real url before fetching. - final UrlResolver getRealUrl; + final UrlResolver? getRealUrl; /// Print error messages. final bool printError; /// The [HttpStatus] code that you can skip retrying if you meet them. - final List skipRetryStatusCode; + final List? skipRetryStatusCode; @override Future obtainKey(PictureConfiguration picture) { @@ -103,7 +103,7 @@ class AdvancedNetworkSvg extends PictureProvider { @override PictureStreamCompleter load(AdvancedNetworkSvg key, - {PictureErrorListener onError}) { + {PictureErrorListener? onError}) { return OneFramePictureStreamCompleter( _loadAsync(key, onError: onError), informationCollector: () sync* { @@ -114,23 +114,23 @@ class AdvancedNetworkSvg extends PictureProvider { } Future _loadAsync(AdvancedNetworkSvg key, - {PictureErrorListener onError}) async { + {PictureErrorListener? onError}) async { assert(key == this); String uId = uid(key.url); if (useDiskCache) { try { - Uint8List _diskCache = await _loadFromDiskCache(key, uId); - if (key.loadedCallback != null) key.loadedCallback(); - return await decode(_diskCache, key.colorFilter, key.toString(), + Uint8List? _diskCache = await _loadFromDiskCache(key, uId); + if (key.loadedCallback != null) key.loadedCallback!(); + return await decode(_diskCache!, key.colorFilter, key.toString(), // TODO: probably a bad idea onError: onError); } catch (e) { if (key.printError) debugPrint(e.toString()); } } - Uint8List imageData = await loadFromRemote( + Uint8List? imageData = await loadFromRemote( key.url, key.header, key.retryLimit, @@ -142,28 +142,28 @@ class AdvancedNetworkSvg extends PictureProvider { printError: key.printError, ); if (imageData != null) { - if (key.loadedCallback != null) key.loadedCallback(); + if (key.loadedCallback != null) key.loadedCallback!(); return await decode(imageData, key.colorFilter, key.toString(), onError: onError); } - if (key.loadFailedCallback != null) key.loadFailedCallback(); + if (key.loadFailedCallback != null) key.loadFailedCallback!(); if (key.fallbackAssetImage != null) { - ByteData imageData = await rootBundle.load(key.fallbackAssetImage); + ByteData imageData = await rootBundle.load(key.fallbackAssetImage!); return await decode( imageData.buffer.asUint8List(), key.colorFilter, key.toString(), onError: onError); } if (key.fallbackImage != null) - return await decode(key.fallbackImage, key.colorFilter, key.toString(), + return await decode(key.fallbackImage!, key.colorFilter, key.toString(), onError: onError); return Future.error(StateError('Failed to load $url.')); } Future decode( - Uint8List imageData, ColorFilter colorFilter, String keyString, - {PictureErrorListener onError}) { + Uint8List imageData, ColorFilter? colorFilter, String keyString, + {PictureErrorListener? onError}) { if (onError != null) return decoder(imageData, colorFilter, keyString)..catchError(onError); return decoder(imageData, colorFilter, keyString); @@ -204,7 +204,7 @@ class AdvancedNetworkSvg extends PictureProvider { /// 1. Check if cache directory exist. If not exist, create it. /// 2. Check if cached file(uid) exist. If yes, load the cache, /// otherwise go to download step. -Future _loadFromDiskCache(AdvancedNetworkSvg key, String uId) async { +Future _loadFromDiskCache(AdvancedNetworkSvg key, String uId) async { if (key.cacheRule == null) { Directory _cacheImagesDirectory = Directory(join((await getTemporaryDirectory()).path, 'imagecache')); @@ -217,7 +217,7 @@ Future _loadFromDiskCache(AdvancedNetworkSvg key, String uId) async { await _cacheImagesDirectory.create(); } - Uint8List imageData = await loadFromRemote( + Uint8List? imageData = await loadFromRemote( key.url, key.header, key.retryLimit, @@ -236,7 +236,7 @@ Future _loadFromDiskCache(AdvancedNetworkSvg key, String uId) async { } } else { DiskCache diskCache = DiskCache(); - Uint8List data = await diskCache.load(uId); + Uint8List? data = await diskCache.load(uId); if (data != null) return data; data = await loadFromRemote( @@ -250,8 +250,8 @@ Future _loadFromDiskCache(AdvancedNetworkSvg key, String uId) async { key.getRealUrl, printError: key.printError, ); - if (data != null) { - await diskCache.save(uId, data, key.cacheRule); + if (data != null && key.cacheRule != null) { + await diskCache.save(uId, data, key.cacheRule!); return data; } } diff --git a/lib/src/transition/raw_image.dart b/lib/src/transition/raw_image.dart index 5e605f6..bf99d2d 100644 --- a/lib/src/transition/raw_image.dart +++ b/lib/src/transition/raw_image.dart @@ -15,7 +15,7 @@ class MyRawImage extends LeafRenderObjectWidget { /// The [scale], [alignment], [repeat], [matchTextDirection] and [filterQuality] arguments must /// not be null. const MyRawImage({ - Key key, + Key? key, this.image, this.width, this.height, @@ -37,19 +37,19 @@ class MyRawImage extends LeafRenderObjectWidget { super(key: key); /// The image to display. - final ui.Image image; + final ui.Image? image; /// If non-null, require the image to have this width. /// /// If null, the image will pick a size that best preserves its intrinsic /// aspect ratio. - final double width; + final double? width; /// If non-null, require the image to have this height. /// /// If null, the image will pick a size that best preserves its intrinsic /// aspect ratio. - final double height; + final double? height; /// Specifies the image's scale. /// @@ -57,7 +57,7 @@ class MyRawImage extends LeafRenderObjectWidget { final double scale; /// If non-null, this color is blended with each image pixel using [colorBlendMode]. - final Color color; + final Color? color; /// Used to set the filterQuality of the image /// Use the "low" quality setting to scale the image, which corresponds to @@ -73,13 +73,13 @@ class MyRawImage extends LeafRenderObjectWidget { /// See also: /// /// * [BlendMode], which includes an illustration of the effect of each blend mode. - final BlendMode colorBlendMode; + final BlendMode? colorBlendMode; /// How to inscribe the image into the space allocated during layout. /// /// The default varies based on the other fields. See the discussion at /// [paintImage]. - final BoxFit fit; + final BoxFit? fit; /// How to align the image within its bounds. /// @@ -118,7 +118,7 @@ class MyRawImage extends LeafRenderObjectWidget { /// region of the image above and below the center slice will be stretched /// only horizontally and the region of the image to the left and right of /// the center slice will be stretched only vertically. - final Rect centerSlice; + final Rect? centerSlice; /// Whether to paint the image in the direction of the [TextDirection]. /// @@ -148,7 +148,7 @@ class MyRawImage extends LeafRenderObjectWidget { /// * [Paint.invertColors], for the dart:ui implementation. final bool invertColors; - final ui.ImageFilter imageFilter; + final ui.ImageFilter? imageFilter; @override MyRenderImage createRenderObject(BuildContext context) { @@ -238,21 +238,21 @@ class MyRenderImage extends RenderBox { /// must not be null. The [textDirection] argument must not be null if /// [alignment] will need resolving or if [matchTextDirection] is true. MyRenderImage({ - ui.Image image, - double width, - double height, + ui.Image? image, + double? width, + double? height, double scale = 1.0, - Color color, - BlendMode colorBlendMode, - BoxFit fit, + Color? color, + BlendMode? colorBlendMode, + BoxFit? fit, AlignmentGeometry alignment = Alignment.center, ImageRepeat repeat = ImageRepeat.noRepeat, - Rect centerSlice, + Rect? centerSlice, bool matchTextDirection = false, - TextDirection textDirection, + TextDirection? textDirection, bool invertColors = false, FilterQuality filterQuality = FilterQuality.low, - ui.ImageFilter imageFilter, + ui.ImageFilter? imageFilter, }) : assert(scale != null), assert(repeat != null), assert(alignment != null), @@ -276,8 +276,8 @@ class MyRenderImage extends RenderBox { _updateColorFilter(); } - Alignment _resolvedAlignment; - bool _flipHorizontally; + Alignment? _resolvedAlignment; + bool? _flipHorizontally; void _resolve() { if (_resolvedAlignment != null) return; @@ -293,9 +293,9 @@ class MyRenderImage extends RenderBox { } /// The image to display. - ui.Image get image => _image; - ui.Image _image; - set image(ui.Image value) { + ui.Image? get image => _image; + ui.Image? _image; + set image(ui.Image? value) { if (value == _image) return; _image = value; markNeedsPaint(); @@ -306,9 +306,9 @@ class MyRenderImage extends RenderBox { /// /// If null, the image will pick a size that best preserves its intrinsic /// aspect ratio. - double get width => _width; - double _width; - set width(double value) { + double? get width => _width; + double? _width; + set width(double? value) { if (value == _width) return; _width = value; markNeedsLayout(); @@ -318,9 +318,9 @@ class MyRenderImage extends RenderBox { /// /// If null, the image will pick a size that best preserves its intrinsic /// aspect ratio. - double get height => _height; - double _height; - set height(double value) { + double? get height => _height; + double? _height; + set height(double? value) { if (value == _height) return; _height = value; markNeedsLayout(); @@ -338,20 +338,20 @@ class MyRenderImage extends RenderBox { markNeedsLayout(); } - ColorFilter _colorFilter; + ColorFilter? _colorFilter; void _updateColorFilter() { if (_color == null) _colorFilter = null; else _colorFilter = - ColorFilter.mode(_color, _colorBlendMode ?? BlendMode.srcIn); + ColorFilter.mode(_color!, _colorBlendMode ?? BlendMode.srcIn); } /// If non-null, this color is blended with each image pixel using [colorBlendMode]. - Color get color => _color; - Color _color; - set color(Color value) { + Color? get color => _color; + Color? _color; + set color(Color? value) { if (value == _color) return; _color = value; _updateColorFilter(); @@ -379,9 +379,9 @@ class MyRenderImage extends RenderBox { /// See also: /// /// * [BlendMode], which includes an illustration of the effect of each blend mode. - BlendMode get colorBlendMode => _colorBlendMode; - BlendMode _colorBlendMode; - set colorBlendMode(BlendMode value) { + BlendMode? get colorBlendMode => _colorBlendMode; + BlendMode? _colorBlendMode; + set colorBlendMode(BlendMode? value) { if (value == _colorBlendMode) return; _colorBlendMode = value; _updateColorFilter(); @@ -392,9 +392,9 @@ class MyRenderImage extends RenderBox { /// /// The default varies based on the other fields. See the discussion at /// [paintImage]. - BoxFit get fit => _fit; - BoxFit _fit; - set fit(BoxFit value) { + BoxFit? get fit => _fit; + BoxFit? _fit; + set fit(BoxFit? value) { if (value == _fit) return; _fit = value; markNeedsPaint(); @@ -430,9 +430,9 @@ class MyRenderImage extends RenderBox { /// region of the image above and below the center slice will be stretched /// only horizontally and the region of the image to the left and right of /// the center slice will be stretched only vertically. - Rect get centerSlice => _centerSlice; - Rect _centerSlice; - set centerSlice(Rect value) { + Rect? get centerSlice => _centerSlice; + Rect? _centerSlice; + set centerSlice(Rect? value) { if (value == _centerSlice) return; _centerSlice = value; markNeedsPaint(); @@ -479,17 +479,17 @@ class MyRenderImage extends RenderBox { /// This may be changed to null, but only after the [alignment] and /// [matchTextDirection] properties have been changed to values that do not /// depend on the direction. - TextDirection get textDirection => _textDirection; - TextDirection _textDirection; - set textDirection(TextDirection value) { + TextDirection? get textDirection => _textDirection; + TextDirection? _textDirection; + set textDirection(TextDirection? value) { if (_textDirection == value) return; _textDirection = value; _markNeedResolution(); } - ui.ImageFilter get imageFilter => _imageFilter; - ui.ImageFilter _imageFilter; - set imageFilter(ui.ImageFilter value) { + ui.ImageFilter? get imageFilter => _imageFilter; + ui.ImageFilter? _imageFilter; + set imageFilter(ui.ImageFilter? value) { if (_imageFilter == value) return; _imageFilter = value; _markNeedResolution(); @@ -513,8 +513,8 @@ class MyRenderImage extends RenderBox { if (_image == null) return constraints.smallest; return constraints.constrainSizeAndAttemptToPreserveAspectRatio(Size( - _image.width.toDouble() / _scale, - _image.height.toDouble() / _scale, + _image!.width.toDouble() / _scale, + _image!.height.toDouble() / _scale, )); } @@ -565,14 +565,14 @@ class MyRenderImage extends RenderBox { myPaintImage( canvas: context.canvas, rect: offset & size, - image: _image, + image: _image!, scale: _scale, colorFilter: _colorFilter, fit: _fit, - alignment: _resolvedAlignment, + alignment: _resolvedAlignment ?? Alignment.center, centerSlice: _centerSlice, repeat: _repeat, - flipHorizontally: _flipHorizontally, + flipHorizontally: _flipHorizontally ?? false, invertColors: invertColors, filterQuality: _filterQuality, imageFilter: imageFilter, @@ -677,19 +677,19 @@ class MyRenderImage extends RenderBox { /// * [DecorationImage], which holds a configuration for calling this function. /// * [BoxDecoration], which uses this function to paint a [DecorationImage]. void myPaintImage({ - @required Canvas canvas, - @required Rect rect, - @required ui.Image image, + required Canvas canvas, + required Rect rect, + required ui.Image image, double scale = 1.0, - ColorFilter colorFilter, - BoxFit fit, + ColorFilter? colorFilter, + BoxFit? fit, Alignment alignment = Alignment.center, - Rect centerSlice, + Rect? centerSlice, ImageRepeat repeat = ImageRepeat.noRepeat, bool flipHorizontally = false, bool invertColors = false, FilterQuality filterQuality = FilterQuality.low, - ui.ImageFilter imageFilter, + ui.ImageFilter? imageFilter, }) { assert(canvas != null); assert(image != null); @@ -699,14 +699,14 @@ void myPaintImage({ if (rect.isEmpty) return; Size outputSize = rect.size; Size inputSize = Size(image.width.toDouble(), image.height.toDouble()); - Offset sliceBorder; + Offset? sliceBorder; if (centerSlice != null) { sliceBorder = Offset( centerSlice.left + inputSize.width - centerSlice.right, centerSlice.top + inputSize.height - centerSlice.bottom, ); - outputSize -= sliceBorder; - inputSize -= sliceBorder; + outputSize = Size(outputSize.width - sliceBorder.dx, outputSize.height - sliceBorder.dy); + inputSize = Size(inputSize.width - sliceBorder.dx, inputSize.height - sliceBorder.dy); } fit ??= centerSlice == null ? BoxFit.scaleDown : BoxFit.fill; assert(centerSlice == null || (fit != BoxFit.none && fit != BoxFit.cover)); @@ -714,9 +714,10 @@ void myPaintImage({ applyBoxFit(fit, inputSize / scale, outputSize); final Size sourceSize = fittedSizes.source * scale; Size destinationSize = fittedSizes.destination; - if (centerSlice != null) { - outputSize += sliceBorder; - destinationSize += sliceBorder; + if (centerSlice != null && sliceBorder != null) { + outputSize = Size(outputSize.width + sliceBorder.dx, outputSize.height + sliceBorder.dy); + destinationSize = Size(destinationSize.width + sliceBorder.dx, destinationSize.height + sliceBorder.dy); + // We don't have the ability to draw a subset of the image at the same time // as we apply a nine-patch stretch. assert(sourceSize == inputSize, diff --git a/lib/src/transition/transition_to_image.dart b/lib/src/transition/transition_to_image.dart index 2d83954..d013d76 100644 --- a/lib/src/transition/transition_to_image.dart +++ b/lib/src/transition/transition_to_image.dart @@ -10,7 +10,7 @@ import 'package:flutter_advanced_networkimage/provider.dart'; typedef Widget LoadingWidgetBuilder( BuildContext context, double progress, - Uint8List imageData, + Uint8List? imageData, ); typedef Widget PlaceHolderBuilder( @@ -20,8 +20,8 @@ typedef Widget PlaceHolderBuilder( class TransitionToImage extends StatefulWidget { const TransitionToImage({ - Key key, - @required this.image, + Key? key, + required this.image, this.width, this.height, this.borderRadius, @@ -75,7 +75,7 @@ class TransitionToImage extends StatefulWidget { /// aspect ratio. This may result in a sudden change if the size of the /// placeholder image does not match that of the target image. The size is /// also affected by the scale factor. - final double width; + final double? width; /// If non-null, require the image to have this height. /// @@ -83,7 +83,7 @@ class TransitionToImage extends StatefulWidget { /// aspect ratio. This may result in a sudden change if the size of the /// placeholder image does not match that of the target image. The size is /// also affected by the scale factor. - final double height; + final double? height; /// The border radius of the rounded corners. /// @@ -91,10 +91,10 @@ class TransitionToImage extends StatefulWidget { /// exceed width/height. /// /// This value is ignored if [clipper] is non-null. - final BorderRadius borderRadius; + final BorderRadius? borderRadius; /// If non-null, this color is blended with each image pixel using [colorBlendMode]. - final Color color; + final Color? color; /// Used to combine [color] with this image. /// @@ -104,7 +104,7 @@ class TransitionToImage extends StatefulWidget { /// See also: /// /// * [BlendMode], which includes an illustration of the effect of each blend mode. - final BlendMode blendMode; + final BlendMode? blendMode; /// How to inscribe the image into the space allocated during layout. /// @@ -167,20 +167,20 @@ class TransitionToImage extends StatefulWidget { /// * [Paint.invertColors], for the dart:ui implementation. final bool invertColors; - final ImageFilter imageFilter; + final ImageFilter? imageFilter; /// Widget displayed while the target [image] failed to load. final Widget placeholder; /// Widget builder (with reload function) displayed /// while the target [image] failed to load. - final PlaceHolderBuilder placeholderBuilder; + final PlaceHolderBuilder? placeholderBuilder; /// The duration of the fade-out animation for the result. final Duration duration; /// The tween of the fade-out animation for the result. - final Tween tween; + final Tween? tween; /// The curve of the fade-out animation for the result. final Curve curve; @@ -193,7 +193,7 @@ class TransitionToImage extends StatefulWidget { /// Widget builder (with loading progress) displayed /// when the target [image] is loading. - final LoadingWidgetBuilder loadingWidgetBuilder; + final LoadingWidgetBuilder? loadingWidgetBuilder; /// Enable an internal [GestureDetector] for manually refreshing. final bool enableRefresh; @@ -206,10 +206,10 @@ class TransitionToImage extends StatefulWidget { final bool disableMemoryCacheIfFailed; /// The callback will fire when the image loaded. - final VoidCallback loadedCallback; + final VoidCallback? loadedCallback; /// The callback will fire when the image failed to load. - final VoidCallback loadFailedCallback; + final VoidCallback? loadFailedCallback; /// If set to enable, the [loadedCallback] or [loadFailedCallback] /// will fire again. @@ -236,15 +236,15 @@ enum TransitionType { class _TransitionToImageState extends State with SingleTickerProviderStateMixin { - AnimationController _controller; - Animation _animation; + late AnimationController _controller; + late Animation _animation; Tween _fadeTween = Tween(begin: 0.0, end: 1.0); Tween _slideTween = Tween(begin: const Offset(0.0, -1.0), end: Offset.zero); - ImageStream _imageStream; - ImageInfo _imageInfo; - Uint8List _imageData; + ImageStream? _imageStream; + ImageInfo? _imageInfo; + Uint8List? _imageData; double _progress = 0.0; _TransitionStatus _status = _TransitionStatus.start; @@ -268,9 +268,9 @@ class _TransitionToImageState extends State _controller = AnimationController(vsync: this, duration: widget.duration) ..addListener(() => setState(() {})); if (widget.transitionType == TransitionType.fade) { - _fadeTween = widget.tween ?? Tween(begin: 0.0, end: 1.0); + _fadeTween = (widget.tween as Tween?) ?? Tween(begin: 0.0, end: 1.0); } else if (widget.transitionType == TransitionType.slide) { - _slideTween = widget.tween ?? + _slideTween = (widget.tween as Tween?) ?? Tween(begin: const Offset(0.0, -1.0), end: Offset.zero); } _animation = CurvedAnimation(parent: _controller, curve: widget.curve); @@ -298,7 +298,7 @@ class _TransitionToImageState extends State @override void dispose() { - _imageStream.removeListener( + _imageStream?.removeListener( ImageStreamListener(_updateImage, onError: _catchBadImage)); _controller.dispose(); super.dispose(); @@ -340,7 +340,7 @@ class _TransitionToImageState extends State _imageProvider.evict(); } - final ImageStream oldImageStream = _imageStream; + final ImageStream? oldImageStream = _imageStream; if (_imageProvider is AdvancedNetworkImage && widget.loadingWidgetBuilder != null) { var callback = (_imageProvider as AdvancedNetworkImage).loadingProgress; @@ -363,16 +363,16 @@ class _TransitionToImageState extends State _imageStream = _imageProvider.resolve(createLocalImageConfiguration( context, size: widget.width != null && widget.height != null - ? Size(widget.width, widget.height) + ? Size(widget.width!, widget.height!) : null, )); if (_imageInfo != null && !reload && - (_imageStream.key == oldImageStream?.key)) { + (_imageStream?.key == oldImageStream?.key)) { if (widget.forceRebuildWidget) { if (widget.loadedCallback != null) - widget.loadedCallback(); - else if (widget.loadFailedCallback != null) widget.loadFailedCallback(); + widget.loadedCallback!(); + else if (widget.loadFailedCallback != null) widget.loadFailedCallback!(); } setState(() => _status = _TransitionStatus.completed); } else { @@ -380,7 +380,7 @@ class _TransitionToImageState extends State oldImageStream?.removeListener( ImageStreamListener(_updateImage, onError: _catchBadImage)); - _imageStream.addListener( + _imageStream?.addListener( ImageStreamListener(_updateImage, onError: _catchBadImage), ); _resolveStatus(); @@ -391,17 +391,17 @@ class _TransitionToImageState extends State _imageInfo = info; if (_imageInfo != null) { _resolveStatus(); - if (widget.loadedCallback != null) widget.loadedCallback(); + if (widget.loadedCallback != null) widget.loadedCallback!(); if (widget.disableMemoryCache) _imageProvider.evict(); } } - void _catchBadImage(dynamic exception, StackTrace stackTrace) { + void _catchBadImage(dynamic exception, StackTrace? stackTrace) { if (widget.printError) print('$exception\n$stackTrace'); setState(() => _status = _TransitionStatus.failed); _resolveStatus(); - if (widget.loadFailedCallback != null) widget.loadFailedCallback(); + if (widget.loadFailedCallback != null) widget.loadFailedCallback!(); if (widget.disableMemoryCache || widget.disableMemoryCacheIfFailed) _imageProvider.evict(); } @@ -410,7 +410,7 @@ class _TransitionToImageState extends State Widget build(BuildContext context) { return _status == _TransitionStatus.failed ? widget.placeholderBuilder != null - ? widget.placeholderBuilder(context, () => _getImage(reload: true)) + ? widget.placeholderBuilder!(context, () => _getImage(reload: true)) : widget.enableRefresh ? GestureDetector( onTap: () => _getImage(reload: true), @@ -420,11 +420,11 @@ class _TransitionToImageState extends State : _status == _TransitionStatus.start || _status == _TransitionStatus.loading ? widget.loadingWidgetBuilder != null - ? widget.loadingWidgetBuilder(context, _progress, _imageData) + ? widget.loadingWidgetBuilder!(context, _progress, _imageData) : widget.loadingWidget : widget.transitionType == TransitionType.fade ? FadeTransition( - opacity: _fadeTween.animate(_animation), + opacity: _fadeTween.animate(_animation as Animation), child: widget.borderRadius != null ? ClipRRect( borderRadius: widget.borderRadius, @@ -433,7 +433,7 @@ class _TransitionToImageState extends State : buildRawImage(), ) : SlideTransition( - position: _slideTween.animate(_animation), + position: _slideTween.animate(_animation as Animation), child: widget.borderRadius != null ? ClipRRect( borderRadius: widget.borderRadius, diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 97e6a4a..43b0812 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -295,16 +295,16 @@ typedef Future UrlResolver(); typedef void LoadingProgress(double progress, List data); /// Fetch the image from network. -Future loadFromRemote( +Future loadFromRemote( String url, - Map header, + Map? header, int retryLimit, Duration retryDuration, double retryDurationFactor, Duration timeoutDuration, - LoadingProgress loadingProgress, - UrlResolver getRealUrl, { - List skipRetryStatusCode, + LoadingProgress? loadingProgress, + UrlResolver? getRealUrl, { + List? skipRetryStatusCode, bool printError = false, }) async { assert(url != null); @@ -314,11 +314,11 @@ Future loadFromRemote( skipRetryStatusCode ??= []; /// Retry mechanism. - Future run(Future f(), int retryLimit, + Future run(Future f(), int retryLimit, Duration retryDuration, double retryDurationFactor) async { for (int t in List.generate(retryLimit + 1, (int t) => t + 1)) { try { - http.Response res = await f(); + http.Response? res = await f(); if (res != null) { if ([HttpStatus.ok, HttpStatus.partialContent] .contains(res.statusCode) && @@ -328,7 +328,7 @@ Future loadFromRemote( if (printError) debugPrint( 'Failed to load, response status code: ${res.statusCode.toString()}.'); - if (skipRetryStatusCode.contains(res.statusCode)) return null; + if (skipRetryStatusCode!.contains(res.statusCode)) return null; } } } catch (e) { @@ -344,7 +344,7 @@ Future loadFromRemote( List buffer = []; bool acceptRangesHeader = false; - http.Response _response; + http.Response? _response; _response = await run(() async { String _url = url; if (getRealUrl != null) _url = (await getRealUrl()) ?? url; @@ -403,15 +403,15 @@ bool get isInDebugMode { } class DoubleTween extends Tween { - DoubleTween({double begin, double end}) : super(begin: begin, end: end); + DoubleTween({double? begin, double? end}) : super(begin: begin, end: end); @override - double lerp(double t) => (begin + (end - begin) * t); + double lerp(double t) => begin != null && end != null ? (begin! + (end! - begin!) * t) : 0; } class OffsetTween extends Tween { - OffsetTween({Offset begin, Offset end}) : super(begin: begin, end: end); + OffsetTween({Offset? begin, Offset? end}) : super(begin: begin, end: end); @override - Offset lerp(double t) => (begin + (end - begin) * t); + Offset lerp(double t) => begin != null && end != null ? (begin! + (end! - begin!) * t) : Offset(0, 0); } diff --git a/lib/src/zoomable/zoomable_list.dart b/lib/src/zoomable/zoomable_list.dart index 2aa74c1..84825ba 100644 --- a/lib/src/zoomable/zoomable_list.dart +++ b/lib/src/zoomable/zoomable_list.dart @@ -2,8 +2,8 @@ import 'package:flutter/widgets.dart'; class ZoomableList extends StatefulWidget { ZoomableList({ - Key key, - @required this.child, + Key? key, + required this.child, this.childKey, this.maxScale: 1.4, this.enablePan: true, @@ -21,18 +21,18 @@ class ZoomableList extends StatefulWidget { assert(enableFling != null), assert(flingFactor != null); - final Widget child; + final Widget? child; @deprecated - final GlobalKey childKey; + final GlobalKey? childKey; final double maxScale; final bool enableZoom; final bool enablePan; - final double maxWidth; + final double? maxWidth; final double maxHeight; final int zoomSteps; final bool enableFling; final double flingFactor; - final VoidCallback onTap; + final VoidCallback? onTap; @override _ZoomableListState createState() => _ZoomableListState(); @@ -52,11 +52,11 @@ class _ZoomableListState extends State Size _widgetSize = Size.zero; bool _getContainerSize = false; - AnimationController _controller; - AnimationController _flingController; - Animation _zoomAnimation; - Animation _panOffsetAnimation; - Animation _flingAnimation; + late AnimationController _controller; + late AnimationController _flingController; + Animation? _zoomAnimation; + Animation? _panOffsetAnimation; + Animation? _flingAnimation; @override void initState() { @@ -77,12 +77,12 @@ class _ZoomableListState extends State void _handleReset() { _zoomAnimation = Tween(begin: 1.0, end: _zoom) .animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut)) - ..addListener(() => setState(() => _zoom = _zoomAnimation.value)); + ..addListener(() => setState(() => _zoom = _zoomAnimation!.value)); _panOffsetAnimation = Tween( begin: Offset(0.0, _panOffset.dy), end: _panOffset) .animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut)) ..addListener( - () => setState(() => _panOffset = _panOffsetAnimation.value)); + () => setState(() => _panOffset = _panOffsetAnimation!.value)); if (_zoom < 0) _controller.forward(from: 1.0); else @@ -107,7 +107,7 @@ class _ZoomableListState extends State void _onScaleUpdate(ScaleUpdateDetails details) { if (!_getContainerSize) { - final RenderBox box = _key.currentContext.findRenderObject(); + final RenderBox box = _key.currentContext!.findRenderObject() as RenderBox; if (box.size == _containerSize) { _getContainerSize = true; } else { @@ -151,7 +151,7 @@ class _ZoomableListState extends State void _onScaleEnd(ScaleEndDetails details) { if (!_getContainerSize) { - final RenderBox box = _key.currentContext.findRenderObject(); + final RenderBox box = _key.currentContext!.findRenderObject() as RenderBox; if (box.size == _containerSize) { _getContainerSize = true; } else { @@ -163,7 +163,7 @@ class _ZoomableListState extends State final double magnitude = velocity.distance; if (magnitude > 800.0 * _zoom && widget.enableFling) { final Offset direction = velocity / magnitude; - final double distance = (Offset.zero & context.size).shortestSide; + final double distance = (Offset.zero & (context.size ?? Size(0, 0))).shortestSide; final Offset endOffset = _panOffset + direction * distance * widget.flingFactor * 0.5; _flingAnimation = Tween( @@ -179,7 +179,7 @@ class _ZoomableListState extends State ), ), ).animate(_flingController) - ..addListener(() => setState(() => _panOffset = _flingAnimation.value)); + ..addListener(() => setState(() => _panOffset = _flingAnimation!.value)); _flingController ..value = 0.0 diff --git a/lib/src/zoomable/zoomable_widget.dart b/lib/src/zoomable/zoomable_widget.dart index 8e8c7d6..b634ae7 100644 --- a/lib/src/zoomable/zoomable_widget.dart +++ b/lib/src/zoomable/zoomable_widget.dart @@ -6,7 +6,7 @@ import 'package:flutter_advanced_networkimage/src/utils.dart'; class ZoomableWidget extends StatefulWidget { ZoomableWidget({ - Key key, + Key? key, this.minScale: 0.7, this.maxScale: 1.4, this.initialScale: 1.0, @@ -74,10 +74,10 @@ class ZoomableWidget extends StatefulWidget { final double panLimit; /// The child widget that is display. - final Widget child; + final Widget? child; /// Tap callback for this widget. - final VoidCallback onTap; + final VoidCallback? onTap; /// Allow users to zoom with double tap steps by steps. final int zoomSteps; @@ -95,7 +95,7 @@ class ZoomableWidget extends StatefulWidget { final double flingFactor; /// When the scale value changed, the callback will be invoked. - final ValueChanged onZoomChanged; + final ValueChanged? onZoomChanged; /// The duration of reset animation. final Duration resetDuration; @@ -134,7 +134,7 @@ class _ZoomableWidgetState extends State { void _onScaleStart(ScaleStartDetails details) { if (_childSize == Size.zero) { - final RenderBox renderbox = _key.currentContext.findRenderObject(); + final RenderBox renderbox = _key.currentContext!.findRenderObject() as RenderBox; _childSize = renderbox.size; } setState(() { @@ -159,7 +159,7 @@ class _ZoomableWidgetState extends State { if (widget.enableZoom && details.scale != 1.0) { _zoom = (_previousZoom * details.scale) .clamp(widget.minScale, widget.maxScale); - if (widget.onZoomChanged != null) widget.onZoomChanged(_zoom); + if (widget.onZoomChanged != null) widget.onZoomChanged!(_zoom); } }); @@ -204,7 +204,7 @@ class _ZoomableWidgetState extends State { final double magnitude = velocity.distance; if (magnitude > 800.0 * _zoom && widget.enableFling) { final Offset direction = velocity / magnitude; - final double distance = (Offset.zero & context.size).shortestSide; + final double distance = (Offset.zero & (context.size ?? Size(0, 0))).shortestSide; final Offset endOffset = _pan + direction * distance * widget.flingFactor * 0.5; _pan = Offset( @@ -251,7 +251,7 @@ class _ZoomableWidgetState extends State { setState(() { _zoom = _tmpZoom; - if (widget.onZoomChanged != null) widget.onZoomChanged(_zoom); + if (widget.onZoomChanged != null) widget.onZoomChanged!(_zoom); _pan = Offset.zero; _rotation = 0.0; _previousZoom = _tmpZoom; @@ -326,12 +326,12 @@ class _ZoomableWidgetLayout extends MultiChildLayoutDelegate { class _ZoomableChild extends ImplicitlyAnimatedWidget { const _ZoomableChild({ - Duration duration, + Duration duration = Duration.zero, Curve curve = Curves.linear, - @required this.zoom, - @required this.panOffset, - @required this.rotation, - @required this.child, + required this.zoom, + required this.panOffset, + required this.rotation, + required this.child, }) : super(duration: duration, curve: curve); final double zoom; @@ -345,33 +345,37 @@ class _ZoomableChild extends ImplicitlyAnimatedWidget { } class _ZoomableChildState extends AnimatedWidgetBaseState<_ZoomableChild> { - DoubleTween _zoom; - OffsetTween _panOffset; - OffsetTween _zoomOriginOffset; - DoubleTween _rotation; + DoubleTween? _zoom; + OffsetTween? _panOffset; + OffsetTween? _zoomOriginOffset; + DoubleTween? _rotation; @override void forEachTween(visitor) { _zoom = visitor( - _zoom, widget.zoom, (dynamic value) => DoubleTween(begin: value)); + _zoom, widget.zoom, (dynamic value) => DoubleTween(begin: value)) as DoubleTween; _panOffset = visitor(_panOffset, widget.panOffset, - (dynamic value) => OffsetTween(begin: value)); + (dynamic value) => OffsetTween(begin: value)) as OffsetTween; _rotation = visitor(_rotation, widget.rotation, - (dynamic value) => DoubleTween(begin: value)); + (dynamic value) => DoubleTween(begin: value)) as DoubleTween; } @override Widget build(BuildContext context) { return Transform( alignment: Alignment.center, - origin: Offset(-_panOffset.evaluate(animation).dx, - -_panOffset.evaluate(animation).dy), - transform: Matrix4.identity() - ..translate(_panOffset.evaluate(animation).dx, - _panOffset.evaluate(animation).dy) - ..scale(_zoom.evaluate(animation), _zoom.evaluate(animation)), + origin: _panOffset == null + ? Offset(0, 0) + : Offset(-_panOffset!.evaluate(animation).dx, + -_panOffset!.evaluate(animation).dy), + transform: _panOffset == null || _zoom == null + ? Matrix4.identity() + : Matrix4.identity() + ..translate(_panOffset!.evaluate(animation).dx, + _panOffset!.evaluate(animation).dy) + ..scale(_zoom!.evaluate(animation), _zoom!.evaluate(animation)), child: Transform.rotate( - angle: _rotation.evaluate(animation), + angle: _rotation?.evaluate(animation) ?? 0, child: widget.child, ), ); diff --git a/pubspec.yaml b/pubspec.yaml index 21867a3..d480810 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,5 +18,5 @@ dev_dependencies: test: any environment: - sdk: ">=2.10.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" flutter: ">=2.0.0 <3.0.0" diff --git a/test/cache_test.dart b/test/cache_test.dart index c6f88b2..656d765 100644 --- a/test/cache_test.dart +++ b/test/cache_test.dart @@ -1,5 +1,6 @@ import 'dart:io'; import 'dart:convert'; +import 'dart:typed_data'; import 'package:path/path.dart'; import 'package:test/test.dart'; @@ -28,76 +29,76 @@ void main() { return null; }); - test('=> non-null test', () async { - await DiskCache().keepCacheHealth(); + // test('=> non-null test', () async { + // await DiskCache().keepCacheHealth(); - expect(() => CacheRule(maxAge: null), throwsAssertionError); - expect(() => CacheRule(storeDirectory: null), throwsAssertionError); - expect(() => CacheRule(checksum: null), throwsAssertionError); + // expect(() => CacheRule(maxAge: null), throwsAssertionError); + // expect(() => CacheRule(storeDirectory: null), throwsAssertionError); + // expect(() => CacheRule(checksum: null), throwsAssertionError); - expect(() => DiskCache()..maxEntries = null, throwsAssertionError); - expect(() => DiskCache()..maxSizeBytes = null, throwsAssertionError); - expect(() => DiskCache()..maxCommitOps = null, throwsAssertionError); + // expect(() => DiskCache()..maxEntries = null, throwsAssertionError); + // expect(() => DiskCache()..maxSizeBytes = null, throwsAssertionError); + // expect(() => DiskCache()..maxCommitOps = null, throwsAssertionError); - expect(() => DiskCache()..maxEntries = -1, throwsAssertionError); - expect(() => DiskCache()..maxSizeBytes = -1, throwsAssertionError); - expect(() => DiskCache()..maxCommitOps = -1, throwsAssertionError); - }); + // expect(() => DiskCache()..maxEntries = -1, throwsAssertionError); + // expect(() => DiskCache()..maxSizeBytes = -1, throwsAssertionError); + // expect(() => DiskCache()..maxCommitOps = -1, throwsAssertionError); + // }); test('=> save and load', () async { DiskCache().printError = true; expect( - await DiskCache().save('aaa'.hashCode.toString(), utf8.encode('hello'), + await DiskCache().save('aaa'.hashCode.toString(), Uint8List.fromList(utf8.encode('hello')), CacheRule(checksum: true)), true, ); expect( - await DiskCache().save('bbb'.hashCode.toString(), utf8.encode('world'), + await DiskCache().save('bbb'.hashCode.toString(), Uint8List.fromList(utf8.encode('world')), CacheRule(checksum: true)), true, ); expect( await DiskCache().save('ccc'.hashCode.toString(), - utf8.encode('welcome'), CacheRule(checksum: true)), + Uint8List.fromList(utf8.encode('welcome')), CacheRule(checksum: true)), true, ); expect( - await DiskCache().save('ddd'.hashCode.toString(), utf8.encode('to'), + await DiskCache().save('ddd'.hashCode.toString(), Uint8List.fromList(utf8.encode('to')), CacheRule(checksum: true)), true, ); expect( await DiskCache().save('eee'.hashCode.toString(), - utf8.encode('flutter'), CacheRule(checksum: true)), + Uint8List.fromList(utf8.encode('flutter')), CacheRule(checksum: true)), true, ); expect( await DiskCache().load('aaa'.hashCode.toString()), - utf8.encode('hello'), + Uint8List.fromList(utf8.encode('hello')), ); expect( await DiskCache().load('bbb'.hashCode.toString()), - utf8.encode('world'), + Uint8List.fromList(utf8.encode('world')), ); expect( await DiskCache().load('ccc'.hashCode.toString()), - utf8.encode('welcome'), + Uint8List.fromList(utf8.encode('welcome')), ); expect( await DiskCache().load('ddd'.hashCode.toString()), - utf8.encode('to'), + Uint8List.fromList(utf8.encode('to')), ); expect( await DiskCache().load('eee'.hashCode.toString()), - utf8.encode('flutter'), + Uint8List.fromList(utf8.encode('flutter')), ); }); test('=> reach maxAge', () async { expect( await DiskCache().save( 'fff'.hashCode.toString(), - utf8.encode('spring'), + Uint8List.fromList(utf8.encode('spring')), CacheRule( storeDirectory: StoreDirectoryType.document, maxAge: Duration( @@ -113,15 +114,15 @@ void main() { storeDirectory: StoreDirectoryType.document, maxAge: Duration(seconds: 1), )), - utf8.encode('spring')); + Uint8List.fromList(utf8.encode('spring'))); expect(await DiskCache().load('fff'.hashCode.toString(), force: true), - utf8.encode('spring')); + Uint8List.fromList(utf8.encode('spring'))); expect(await DiskCache().load('fff'.hashCode.toString()), null); expect( await DiskCache().save( 'fff'.hashCode.toString(), - utf8.encode('spring'), + Uint8List.fromList(utf8.encode('spring')), CacheRule( storeDirectory: StoreDirectoryType.document, maxAge: Duration( @@ -143,55 +144,55 @@ void main() { DiskCache().maxEntries = 1; expect( await DiskCache().save( - 'ggg'.hashCode.toString(), utf8.encode('summer'), CacheRule()), + 'ggg'.hashCode.toString(), Uint8List.fromList(utf8.encode('summer')), CacheRule()), true, ); expect( await DiskCache().save( - 'hhh'.hashCode.toString(), utf8.encode('autumn'), CacheRule()), + 'hhh'.hashCode.toString(), Uint8List.fromList(utf8.encode('autumn')), CacheRule()), true, ); expect(await DiskCache().load('ggg'.hashCode.toString()), null); expect(await DiskCache().load('hhh'.hashCode.toString()), - utf8.encode('autumn')); + Uint8List.fromList(utf8.encode('autumn'))); DiskCache().maxEntries = 5000; }); test('=> reach maxSizeBytes', () async { DiskCache().maxSizeBytes = 8; expect( await DiskCache().save( - 'iii'.hashCode.toString(), utf8.encode('winter'), CacheRule()), + 'iii'.hashCode.toString(), Uint8List.fromList(utf8.encode('winter')), CacheRule()), true, ); expect( await DiskCache().save( - 'jjj'.hashCode.toString(), utf8.encode('Monday'), CacheRule()), + 'jjj'.hashCode.toString(), Uint8List.fromList(utf8.encode('Monday')), CacheRule()), true, ); expect(await DiskCache().load('iii'.hashCode.toString()), null); expect(await DiskCache().load('jjj'.hashCode.toString()), - utf8.encode('Monday')); + Uint8List.fromList(utf8.encode('Monday'))); DiskCache().maxSizeBytes = 1000 << 20; }); test('=> evict uid', () async { expect( await DiskCache().save( - 'kkk'.hashCode.toString(), utf8.encode('Tuesday'), CacheRule()), + 'kkk'.hashCode.toString(), Uint8List.fromList(utf8.encode('Tuesday')), CacheRule()), true, ); expect(await DiskCache().load('kkk'.hashCode.toString()), - utf8.encode('Tuesday')); + Uint8List.fromList(utf8.encode('Tuesday'))); expect(await DiskCache().evict('kkk'.hashCode.toString()), true); expect(await DiskCache().load('kkk'.hashCode.toString()), null); }); test('=> clear cache', () async { expect( await DiskCache().save( - 'lll'.hashCode.toString(), utf8.encode('Wednesday'), CacheRule()), + 'lll'.hashCode.toString(), Uint8List.fromList(utf8.encode('Wednesday')), CacheRule()), true, ); expect(await DiskCache().load('lll'.hashCode.toString()), - utf8.encode('Wednesday')); + Uint8List.fromList(utf8.encode('Wednesday'))); expect(await DiskCache().clear(), true); expect(await DiskCache().load('lll'.hashCode.toString()), null); }); @@ -199,18 +200,18 @@ void main() { expect(await DiskCache().clear(), true); expect( await DiskCache().save( - 'mmm'.hashCode.toString(), utf8.encode('Thursday'), CacheRule()), + 'mmm'.hashCode.toString(), Uint8List.fromList(utf8.encode('Thursday')), CacheRule()), true, ); expect( - await DiskCache().save('nnn'.hashCode.toString(), utf8.encode('Friday'), + await DiskCache().save('nnn'.hashCode.toString(), Uint8List.fromList(utf8.encode('Friday')), CacheRule(storeDirectory: StoreDirectoryType.document)), true, ); expect(await DiskCache().load('mmm'.hashCode.toString()), - utf8.encode('Thursday')); + Uint8List.fromList(utf8.encode('Thursday'))); expect(await DiskCache().load('nnn'.hashCode.toString()), - utf8.encode('Friday')); + Uint8List.fromList(utf8.encode('Friday'))); expect( await DiskCache().cacheSize(), 'Thursday'.length + 'Friday'.length); expect(await DiskCache().clear(), true); @@ -222,11 +223,11 @@ void main() { expect( await DiskCache().save( - 'ooo'.hashCode.toString(), utf8.encode('Saturday'), CacheRule()), + 'ooo'.hashCode.toString(), Uint8List.fromList(utf8.encode('Saturday')), CacheRule()), true, ); expect(await DiskCache().load('ooo'.hashCode.toString()), - utf8.encode('Saturday')); + Uint8List.fromList(utf8.encode('Saturday'))); var file = File( join((await getTemporaryDirectory()).path, 'imagecache', uid('ooo'))); await DiskCache().keepCacheHealth(); @@ -240,7 +241,7 @@ void main() { expect( await DiskCache().save( 'ooo'.hashCode.toString(), - utf8.encode('Saturday'), + Uint8List.fromList(utf8.encode('Saturday')), CacheRule(maxAge: const Duration(milliseconds: 1))), true, );