5

I use Image.network() to show image from URL this is how I use it

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);
      },
    );

But even when I set errorBuilder or even wrap the whole thing with try/catch This NetworkImageLoadException still show

Full Exception

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)
Fei Whang
  • 209
  • 4
  • 11

5 Answers5

1

None of these would work for me with the current release of Flutter. This is what worked for me.

import 'package:http/http.dart';
...
final String url;
...
class _WebIconState extends State<WebIcon> {
  late Widget imgWidget;
  late bool loaded;

  @override
  void initState() {
    imgWidget = SizedBox.shrink();
    loaded = false;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    Uri? uri = Uri.tryParse(widget.url);
    if (uri == null) {
      return SizedBox.shrink();
    }
    if (!loaded) {
      () async {
        Response resp = await get(uri);
        if (resp.statusCode >= 200 &&
            resp.statusCode < 300 &&
            resp.headers["content-type"] is String &&
            resp.headers["content-type"]!.contains("image")) {
          setState(() {
            imgWidget = Image.memory(resp.bodyBytes);
            loaded = true;
          });
        }

        log("Loaded ${widget.url}");
      }();
    }

    return imgWidget;
  }
sleepwalk
  • 141
  • 4
0

You can use ErrorBuilder for that

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

Find out Documentation from here

Anushka Pubudu
  • 389
  • 3
  • 10
0

I tried also cached_network_image package and also try catch. But I couldn't find the solution. Then I made a basic implementation. I have small pictures so this solution works for me for now.

  import 'package:http/http.dart' as http;

  Map<String, Image?> imageDict = {};
  String name;
  String? profilepiclink;

  Future<Image?> fetchImage() async {
    if (imageDict[name] != null) {
      return imageDict[name];
    } else {
      final response = await http.get(Uri.parse(profilepiclink!));
      if (response.statusCode == 200) {
        // If the server did return a 200 OK response,
        // then parse the JSON.
        Image pic = Image.memory(response.bodyBytes);
        imageDict[name] = pic;
        return pic;
      } else {
        // If the server did not return a 200 OK response,
        // then throw an exception.
        return null;
      }
    }
  }

  Future<Widget> _displayProfilePic() async {
    if (profilepiclink != null) {
      Image? profilPic = await fetchImage();

      return Container(
          width: 30,
          height: 30,
          clipBehavior: Clip.hardEdge,
          child: profilPic ?? const Icon(Icons.person),
          decoration: const BoxDecoration(shape: BoxShape.circle));
    }
    return const SizedBox(width: 30, child: Icon(Icons.person));
  }

  var image = FutureBuilder<Widget>(
            future: _displayProfilePic(),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return snapshot.data!;
              }
              return const Icon(Icons.person);
           })
Muge Cevik
  • 235
  • 4
  • 6
0

In my case, what fixed it in production code was to add a listener in the image resolve with a 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);
        },
      ),
    );

While this works fine in debug / prod, in the tests where I used HttpOverrides.runZoned() with a client that always returns 404, the tests were always failing with an uncaught NetworkImageLoadException.

The fix was to listen to FlutterError at the beginning of the test and only throw if the exception caught was not a NetworkImageLoadException.

WidgetsFlutterBinding.ensureInitialized();
FlutterError.onError = (details) {
  if (details.exception is! NetworkImageLoadException) throw details.exception;
};
Gpack
  • 1,878
  • 3
  • 18
  • 45
-1

in package:flutter/src/painting/_network_image_io.dart


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>>();
    throw image_provider.NetworkImageLoadException(statusCode: response.statusCode, uri: resolved);
}  

That comment is what cause exception.

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.

p2kr
  • 606
  • 6
  • 18