55

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

Jesús Martín
  • 1,293
  • 2
  • 11
  • 11

9 Answers9

66

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,
  );
}
Raymond Ativie
  • 1,747
  • 2
  • 26
  • 50
Shady Aziza
  • 50,824
  • 20
  • 115
  • 113
  • 2
    `You can also listen until the image is loaded` talking about `ImageProvider` would help here. As image contains no listenable. – Rémi Rousselet Apr 11 '18 at 11:20
31

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
Lay Leangsros
  • 9,156
  • 7
  • 34
  • 39
28

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';
Kirill Karmazin
  • 6,256
  • 2
  • 54
  • 42
21

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

Yumarx Polanco
  • 2,195
  • 1
  • 19
  • 33
3

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,
     ),
    
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),
),
Wajid khan
  • 842
  • 9
  • 18
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),
            )
Amit
  • 468
  • 5
  • 16
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

Wasib Hussain
  • 166
  • 1
  • 8
  • 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](/help/how-to-answer). – Community Aug 27 '22 at 07:50
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.

Misbakh Ahmed
  • 119
  • 1
  • 6