Flutter - Default image to Image.network when it fails
Asked Answered
P

9

62

Is there any way you can control exceptions launched by Image.network() so you can provide it a default AssetImage ?

Poulterer answered 11/4, 2018 at 9:45 Comment(3)
What do you mean by exception ? ]Laciniate
Error, for example trying to read a url that doesn't existCachexia
You can return an Image.asset from the errorBuilder property when using Image.network. All the answers below refer to solutions that don't use Image.network.Superphosphate
P
67

It depends on your use case, but one way to do it is to use FadeInImage which has a property of img for the image that is intended to load, and placeholder, well, for the placeholder

FadeInImage(image: NetworkImage(url), placeholder: AssetImage(assetName)

You can also listen until the image is loaded and show a placeholder yourself until fetching the image resolves.

pseudo code

bool _loaded = false;
var img = Image.network(src);
var placeholder = AssetImage(assetName)

@override
void initState() {
  super.initState();
  img.image.resolve(ImageConfiguration()).addListener((i, b) {
    if (mounted) {
      setState(() => _loaded = true);
    }
  });     
}

@override
Widget build(BuildContext context) { 
  return YourWidget(
    child: _loaded ? img : placeholder,
  );
}
Plat answered 11/4, 2018 at 11:16 Comment(1)
You can also listen until the image is loaded talking about ImageProvider would help here. As image contains no listenable.Laciniate
G
32

You can do with FadeInImage.assetNetwork

 child: new Container(
      child: FadeInImage.assetNetwork(
          placeholder: 'assets/place_holder.jpg',
          image:url
      )
  )

and in pubspec.yaml

  assets:
  - assets/place_holder.jpg
Glendaglenden answered 24/1, 2019 at 7:54 Comment(4)
how to handle null url with FadeInImAGE??Denisse
you should put full path, not just name.Boehmenist
placeholder requires absolute path. relative path is not working! Any reasons or suggestions ?Cook
@Md.Sulayman use this https://mcmap.net/q/320102/-flutter-default-image-to-image-network-when-it-failsNork
T
31

There is a new package called cached_network_image which does what you need. Here you can set a "loading" image and an "error" image right out of the box.

A flutter library to show images from the internet and keep them in the cache directory. https://pub.dev/packages/cached_network_image#-readme-tab-

CachedNetworkImage(
        imageUrl: "http://via.placeholder.com/350x150",
        placeholder: (context, url) => new CircularProgressIndicator(),
        errorWidget: (context, url, error) => new Icon(Icons.error),
     ),

or you can use your own asset image as a placeholder for example:

...
placeholder: (context, url) => {return Image.asset('assets/img/my_placeholder.png');},

Add this to your package's pubspec.yaml file:

dependencies:
  cached_network_image: ^1.1.1

and import in your dart code:

import 'package:cached_network_image/cached_network_image.dart';
Transposition answered 14/8, 2019 at 10:56 Comment(2)
this: placeholder: (context, url) => {return Image.asset('assets/img/my_placeholder.png');}, does not work at allRupiah
@Rupiah try using (context) => Image.asset('assets/img/my_placeholder.png'),Tellez
T
24

You can use the loadingBuilder, and erroBuilder properties as specified in the widget official documentation:

               Image.network(
                  'https://example.com/image.jpg',
                  errorBuilder: (context, error, stackTrace) {
                    print(error); //do something
                  },
                  loadingBuilder: (BuildContext context, Widget child,
                      ImageChunkEvent loadingProgress) {
                    if (loadingProgress == null) return child;
                    return Center(
                      child: CircularProgressIndicator(
                        value: loadingProgress.expectedTotalBytes != null
                            ? loadingProgress.cumulativeBytesLoaded /
                                loadingProgress.expectedTotalBytes
                            : null,
                      ),
                    );
                  },
                ),

https://api.flutter.dev/flutter/widgets/Image/loadingBuilder.html https://api.flutter.dev/flutter/widgets/ImageErrorWidgetBuilder.html

Tellez answered 25/10, 2020 at 3:17 Comment(0)
D
5

100% Solution,

  1. add the asset image in pubspec.yaml file, which you want to set as default image.

  2. copy the whole code and use this code where you want to implement.

    FadeInImage(
        image:NetworkImage("your_image_url"),
        placeholder: const AssetImage("your_default_image_path"),
        imageErrorBuilder:(context, error, stackTrace) {
           return Image.asset('your_default_image_path',
               fit: BoxFit.fitWidth
           );
        },
        fit: BoxFit.fitWidth,
     ),
    
Deach answered 6/1, 2023 at 10:6 Comment(0)
I
2

Problem:

Image.Network is not providing any feature/functionality to show error widget if Image not loaded successfully due to any reason.This means your URL should be correct always?

Flutter team uploaded new video about Image Widget on 13-01-2020 (https://www.youtube.com/watch?v=7oIAs-0G4mw) but still they didn't provide any solution.We hope the flutter team will resolve this issue soon.

Solution: You can use Cached network image which is providing a lot of features/functionalities to load image from URL. To read more about Cached network image please visit:

https://pub.dev/packages/cached_network_image

Sample code of Package:

CachedNetworkImage(   
imageUrl: "http://via.placeholder.com/200x150",  
imageBuilder: 
(context, imageProvider) => 
    Container(
     decoration: BoxDecoration(
      image: DecorationImage(
          image: imageProvider,
          fit: BoxFit.cover,
          colorFilter:
              ColorFilter.mode(Colors.red, BlendMode.colorBurn)),
     ),   
    ),   
 placeholder: (context, url) => 
   CircularProgressIndicator(),  
 errorWidget: (context, url, error) 
  => Icon(Icons.error),
),
Illa answered 15/1, 2020 at 13:27 Comment(0)
N
1

i have found the way You can use this

     SizedBox(
              height: 50,
              width: 50,
              child: FadeInImage(
                  height: 50,
                  width: 50,
            fadeInDuration: const Duration(milliseconds: 500),
                  fadeInCurve: Curves.easeInExpo,
                  fadeOutCurve: Curves.easeOutExpo,
                  placeholder: AssetImage("assets/images/common_screen/ic_default_image.jpg"),
                  image: NetworkImage(imageURL
                  ),
                  imageErrorBuilder: (context, error, stackTrace) {
                      return Container(child: Image.asset("assets/images/common_screen/ic_default_image.jpg"));
                  },
                  fit: BoxFit.cover),
            )
Nork answered 27/10, 2021 at 11:5 Comment(0)
A
1
 CachedNetworkImage(
         fit: BoxFit.cover,
         imageUrl: map['message'],
         placeholder: (context, url) =>
         Shimmer.fromColors(
         baseColor: HexColor("#fcfcfc"),
         highlightColor: HexColor("#edebe6"),
         child: Image.network(
         fit: BoxFit.cover,"https://www.haliburtonforest.com/wp-content/uploads/2017/08/placeholder-square.jpg")),
  errorWidget: (context, url, error) =>
   const Icon(Icons.error), )

you can use this code to show a beautiful image loading animation,

add these dependencies to your pubspec.yaml.

shimmer: ^2.0.0

hexcolor: ^2.0.7

cached_network_image: ^3.2.0

Abroms answered 23/8, 2022 at 10:35 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Chios
I
1

You can use loadingBuilder property

Image.network(
    'https://flutter.github.io/assets-for-api-docs/assets/widgets/falcon.jpg',
    loadingBuilder: (BuildContext context, Widget child,
        ImageChunkEvent? loadingProgress) {
      if (loadingProgress == null) {
        return child;
      }
      return Center(
        child: CircularProgressIndicator(
          value: loadingProgress.expectedTotalBytes != null
              ? loadingProgress.cumulativeBytesLoaded /
                  loadingProgress.expectedTotalBytes!
              : null,
        ),
      );
    },
  )

this code will show image loading progress as a CircularProgressIndicator.

Ible answered 1/5, 2023 at 13:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.