当 Image.network() 失败时无法捕获 NetworkImageLoadException

Fei*_*ang 6 flutter flutter-image

我使用 Image.network() 显示来自 URL 的图像,这就是我使用它的方式

Image image = Image.network(
      _auth.currentUser!.photoURL!,
      width: 100.getWidth(context),
      height: 100.getWidth(context),
      frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
        return wasSynchronouslyLoaded
            ? child
            : _profileImagePlaceholder(context);
      },
      loadingBuilder: (context, child, loadingProgress) {
        return loadingProgress == null
            ? child
            : _profileImagePlaceholder(context);
      },
      errorBuilder: (context, error, stackTrace) {
        return _profileImagePlaceholder(context);
      },
    );
Run Code Online (Sandbox Code Playgroud)

但即使当我设置 errorBuilder 甚至用 try/catch 包装整个事情时这NetworkImageLoadException仍然显示

完全例外

The following NetworkImageLoadException was thrown resolving an image codec:
HTTP request failed, statusCode: 403,


When the exception was thrown, this was the stack:
#0      NetworkImage._loadAsync (package:flutter/src/painting/_network_image_io.dart:99:9)
<asynchronous suspension>
...

Image provider:
  NetworkImage("https://firebasestorage.googleapis.com/v0/b/biddee-co.appspot.com/o/profiles%2FdefaultProfile.png?alt=media&token=a4a99031-aabd-4597-b075-77ecb2d3e594",
  scale: 1.0)
Image key:
  NetworkImage("https://firebasestorage.googleapis.com/v0/b/biddee-co.appspot.com/o/profiles%2FdefaultProfile.png?alt=media&token=a4a99031-aabd-4597-b075-77ecb2d3e594",
  scale: 1.0)
Run Code Online (Sandbox Code Playgroud)

Gpa*_*ack 0

就我而言,在生产代码中修复它的方法是在图像解析中添加一个侦听器onError

final image = Image.network(
  // Properties.
  errorBuilder: // ...,
);
image.image.resolve(ImageConfiguration.empty).addListener(
      ImageStreamListener(
        (_, __) { /* You can do something when the image is loaded. */ },
        onError: (_, __) {
          // Evict the object from the cache to retry to fetch it the next
          // time this widget is built.
          imageCache.evict(image.image);
        },
      ),
    );
Run Code Online (Sandbox Code Playgroud)

虽然这在调试/生产中工作得很好,但在我与始终返回 404 的客户端一起使用的测试中HttpOverrides.runZoned(),测试总是失败并出现未捕获的 NetworkImageLoadException。

修复方法是在测试开始时监听 FlutterError,并且仅在捕获的异常不是NetworkImageLoadException.

WidgetsFlutterBinding.ensureInitialized();
FlutterError.onError = (details) {
  if (details.exception is! NetworkImageLoadException) throw details.exception;
};
Run Code Online (Sandbox Code Playgroud)