简体   繁体   English

即使在 Flutter 中定义了 errorBuilder 之后,Image.network 也会抛出错误

[英]Image.network throw error even after defining errorBuilder in Flutter

I am facing some issues with loading images from URLs in Flutter. Here is my code:我在从 Flutter 中的 URL 加载图像时遇到了一些问题。这是我的代码:

  @override
  Widget build(BuildContext context) {
    return ClipRRect(
      borderRadius: BorderRadius.circular(8.0),
      child: Center(
        child: Image.network(
          'https://www.example.com/no-image.jpg', // this image doesn't exist
          fit: BoxFit.cover,
          errorBuilder: (context, error, stackTrace) {
            return Container(
              color: Colors.amber,
              alignment: Alignment.center,
              child: const Text(
                'Whoops!',
                style: TextStyle(fontSize: 30),
              ),
            );
          },
        ),

      ),
    );
  }

I am using Image.network to receive images from a given URL but as the URL does not exist the widget throws a 404 exception, even though the errorBuilder parameter is defined.我正在使用Image.network从给定的 URL 接收图像,但由于 URL 不存在,即使定义了errorBuilder参数,小部件也会引发 404 异常。 It is not only for 404 exceptions but any.network connection errors.它不仅适用于 404 异常,还适用于任何网络连接错误。

Source of exception (flutter file: .../.network_image_io.dart ):异常来源(flutter 文件: .../.network_image_io.dart ):

Future<ui.Codec> _loadAsync(
    NetworkImage key,
    StreamController<ImageChunkEvent> chunkEvents,
    image_provider.DecoderCallback decode,
  ) async {
    try {
      assert(key == this);

      final Uri resolved = Uri.base.resolve(key.url);

      final HttpClientRequest request = await _httpClient.getUrl(resolved);

      headers?.forEach((String name, String value) {
        request.headers.add(name, value);
      });
      final HttpClientResponse response = await request.close();
      if (response.statusCode != HttpStatus.ok) {
        // The network may be only temporarily unavailable, or the file will be
        // added on the server later. Avoid having future calls to resolve
        // fail to check the network again.
        await response.drain<List<int>>(<int>[]);
        throw image_provider.NetworkImageLoadException(
            statusCode: response.statusCode, uri: resolved);
      }

      final Uint8List bytes = await consolidateHttpClientResponseBytes(
        response,
        onBytesReceived: (int cumulative, int? total) {
          chunkEvents.add(ImageChunkEvent(
            cumulativeBytesLoaded: cumulative,
            expectedTotalBytes: total,
          ));
        },
      );
      if (bytes.lengthInBytes == 0)
        throw Exception('NetworkImage is an empty file: $resolved');

      return decode(bytes);
    } catch (e) {
      // Depending on where the exception was thrown, the image cache may not
      // have had a chance to track the key in the cache at all.
      // Schedule a microtask to give the cache a chance to add the key.
      scheduleMicrotask(() {
        PaintingBinding.instance!.imageCache!.evict(key);
      });
      print(e);
      rethrow; // <<<<<<<< Exception throw here: NetworkImageLoadException (HTTP request failed, statusCode: 404, https://www.example.com/no-image.jpg)
    } finally {
      chunkEvents.close();
    }
  }

I am wondering if it is a bug or I've made a mistake.我想知道这是一个错误还是我犯了一个错误。

I have handled the network image issue related to 404 by using an errorBuilder.我已经使用 errorBuilder 处理了与 404 相关的网络图像问题。

Image.network('Your image url...',
        errorBuilder: (BuildContext context, Object exception, StackTrace stackTrace) {
            return Text('Your error widget...');
        },
    ),

Yes, you are correct with the implementation.是的,您对实施是正确的。 So the thing is, NetworkImage tries to load the image and fails to load it.所以问题是,NetworkImage 尝试加载图像并且无法加载它。 And hence, the _loadAsync() method rethrows the exception.因此, _loadAsync()方法会rethrows引发异常。 Now, as you have provided errorBuilder , the framework uses that widget to show when an exception occurs.现在,正如您提供的errorBuilder ,框架使用该小部件来显示何时发生异常。 Hence, you are getting an exception that is rethrown from the framework but is handled as you have provided errorBuilder .因此,您会得到一个异常,该异常是从框架中重新抛出的,但会按照您提供errorBuilder进行处理。 Now, if you remove the errorBuilder you will get the exception logged in debug console, as well as the user, will be able to see that red exception screen if in debug mode and grey screen in release mode.现在,如果您删除errorBuilder ,您将在调试控制台中记录异常,并且用户将能够在调试模式下看到红色异常屏幕,在发布模式下看到灰色屏幕。

So, you are correct with the implementation as well as your doubt, but you missed the exact explanation of errorBuilder .因此,您对实现以及您的疑问都是正确的,但是您错过了errorBuilder的确切解释。

I hope this made your doubt clear!我希望这能澄清你的疑问!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM