|
| 1 | +import 'dart:async'; |
| 2 | +// ignore: unnecessary_import |
1 | 3 | import 'dart:typed_data';
|
2 | 4 | import 'dart:ui' as ui show Codec, ImmutableBuffer;
|
3 | 5 | import 'package:extended_image_library/src/extended_resize_image_provider.dart';
|
| 6 | +import 'package:flutter/foundation.dart'; |
4 | 7 | import 'package:flutter/painting.dart' hide imageCache;
|
5 | 8 |
|
6 | 9 | /// The cached raw image data
|
@@ -123,4 +126,102 @@ mixin ExtendedImageProvider<T extends Object> on ImageProvider<T> {
|
123 | 126 | final T key = await obtainKey(configuration);
|
124 | 127 | return cache.evict(key, includeLive: includeLive);
|
125 | 128 | }
|
| 129 | + |
| 130 | + @override |
| 131 | + Future<ImageCacheStatus?> obtainCacheStatus({ |
| 132 | + required ImageConfiguration configuration, |
| 133 | + ImageErrorListener? handleError, |
| 134 | + }) { |
| 135 | + return _obtainCacheStatus( |
| 136 | + configuration: configuration, |
| 137 | + handleError: handleError, |
| 138 | + ); |
| 139 | + } |
| 140 | + |
| 141 | + // copy from offical |
| 142 | + Future<ImageCacheStatus?> _obtainCacheStatus({ |
| 143 | + required ImageConfiguration configuration, |
| 144 | + ImageErrorListener? handleError, |
| 145 | + }) { |
| 146 | + // ignore: unnecessary_null_comparison |
| 147 | + assert(configuration != null); |
| 148 | + final Completer<ImageCacheStatus?> completer = |
| 149 | + Completer<ImageCacheStatus?>(); |
| 150 | + _createErrorHandlerAndKey( |
| 151 | + configuration, |
| 152 | + (T key, ImageErrorListener innerHandleError) { |
| 153 | + completer.complete(imageCache.statusForKey(key)); |
| 154 | + }, |
| 155 | + (T? key, Object exception, StackTrace? stack) async { |
| 156 | + if (handleError != null) { |
| 157 | + handleError(exception, stack); |
| 158 | + } else { |
| 159 | + InformationCollector? collector; |
| 160 | + assert(() { |
| 161 | + collector = () => <DiagnosticsNode>[ |
| 162 | + DiagnosticsProperty<ImageProvider>('Image provider', this), |
| 163 | + DiagnosticsProperty<ImageConfiguration>( |
| 164 | + 'Image configuration', configuration), |
| 165 | + DiagnosticsProperty<T>('Image key', key, defaultValue: null), |
| 166 | + ]; |
| 167 | + return true; |
| 168 | + }()); |
| 169 | + FlutterError.reportError(FlutterErrorDetails( |
| 170 | + context: ErrorDescription( |
| 171 | + 'while checking the cache location of an image'), |
| 172 | + informationCollector: collector, |
| 173 | + exception: exception, |
| 174 | + stack: stack, |
| 175 | + )); |
| 176 | + completer.complete(null); |
| 177 | + } |
| 178 | + }, |
| 179 | + ); |
| 180 | + return completer.future; |
| 181 | + } |
| 182 | + |
| 183 | + /// This method is used by both [resolve] and [obtainCacheStatus] to ensure |
| 184 | + /// that errors thrown during key creation are handled whether synchronous or |
| 185 | + /// asynchronous. |
| 186 | + void _createErrorHandlerAndKey( |
| 187 | + ImageConfiguration configuration, |
| 188 | + _KeyAndErrorHandlerCallback<T> successCallback, |
| 189 | + _AsyncKeyErrorHandler<T?> errorCallback, |
| 190 | + ) { |
| 191 | + T? obtainedKey; |
| 192 | + bool didError = false; |
| 193 | + Future<void> handleError(Object exception, StackTrace? stack) async { |
| 194 | + if (didError) { |
| 195 | + return; |
| 196 | + } |
| 197 | + if (!didError) { |
| 198 | + errorCallback(obtainedKey, exception, stack); |
| 199 | + } |
| 200 | + didError = true; |
| 201 | + } |
| 202 | + |
| 203 | + Future<T> key; |
| 204 | + try { |
| 205 | + key = obtainKey(configuration); |
| 206 | + } catch (error, stackTrace) { |
| 207 | + handleError(error, stackTrace); |
| 208 | + return; |
| 209 | + } |
| 210 | + key.then<void>((T key) { |
| 211 | + obtainedKey = key; |
| 212 | + try { |
| 213 | + successCallback(key, handleError); |
| 214 | + } catch (error, stackTrace) { |
| 215 | + handleError(error, stackTrace); |
| 216 | + } |
| 217 | + }).catchError(handleError); |
| 218 | + } |
126 | 219 | }
|
| 220 | + |
| 221 | +/// Signature for the callback taken by [_createErrorHandlerAndKey]. |
| 222 | +typedef _KeyAndErrorHandlerCallback<T> = void Function( |
| 223 | + T key, ImageErrorListener handleError); |
| 224 | + |
| 225 | +/// Signature used for error handling by [_createErrorHandlerAndKey]. |
| 226 | +typedef _AsyncKeyErrorHandler<T> = Future<void> Function( |
| 227 | + T key, Object exception, StackTrace? stack); |
0 commit comments