imageflutterdartreloadsetstate

Reload cached Network Image upon failure


I have class for images that are displayed in a listview. Sometimes the image fails and setstate does not reload the image nor any method that I have thought of works, even when assigning a unique key value.

The image class returns this code:

CachedNetworkImage(
        imageUrl: widget.url,
        fit: BoxFit.fitWidth,
        progressIndicatorBuilder: (context, url, downloadProgress) =>
            Container(
              alignment: Alignment.center,
              height: MediaQuery.of(context).size.height * 0.5,
              width: MediaQuery.of(context).size.width,
              child: CircularProgressIndicator(
                  value: downloadProgress.progress),
            ),
            errorWidget: (){
              return Container(
                alignment: Alignment.center,
                height: MediaQuery.of(context).size.height * 0.5,
                width: MediaQuery.of(context).size.width,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Icon(
                      Icons.perm_scan_wifi,
                      color: Colors.grey[600],
                      size: 50,
                    ),
                    Padding(
                      padding: const EdgeInsets.only(bottom: 20, top: 25),
                      child: Text(
                        'Failed To Load Image',
                        style: TextStyle(color: Colors.white, fontSize: 17),
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.only(
                          bottom: 12.0, left: 10, right: 10),
                      child: Text(
                        'Check your internet connection and try again.',
                        textAlign: TextAlign.center,
                        style: TextStyle(color: Colors.grey),
                      ),
                    ),
                    FlatButton(
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(8)),
                      child: Text('Retry',
                          style: TextStyle(color: Colors.black)),
                      onPressed: () {
                        setState(() {});
                      },
                      color: Pigment.fromString('#FFCC00'),
                    )
                  ],
                ),
              );
            },
         
        )

Can you please propose a way to reload the image when it fails, I can only use cached network image, no other packages would be useful cuz I was the unique cache key feature.


Solution

  • You can copy paste run full code below
    You can use ValueNotifier to change cacheKey of CachedNetworkImage
    In working demo
    Step 1: image is not loaded in airplane mode
    Step 2: turn off airplane mode
    Step 3: and click Retry button then _networklHasErrorNotifier.value++
    Step 4: ValueListenableBuilder rebuild CachedNetworkImage with new cacheKey

    code snippet

    ValueNotifier<int> _networklHasErrorNotifier = ValueNotifier(0);
    ...
    ValueListenableBuilder(
                    valueListenable: _networklHasErrorNotifier,
                    builder: (BuildContext context, int count, Widget child) {
                      print("rebuild");
                      return CachedNetworkImage(
                        cacheKey: _networklHasErrorNotifier.value.toString(),
    ...                 
    onPressed: () {
            print("clicked");
            _networklHasErrorNotifier.value++;      
          },                    
    

    working demo

    enter image description here

    full code

    import 'package:cached_network_image/cached_network_image.dart';
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      ValueNotifier<int> _networklHasErrorNotifier = ValueNotifier(0);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                ValueListenableBuilder(
                    valueListenable: _networklHasErrorNotifier,
                    builder: (BuildContext context, int count, Widget child) {
                      print("rebuild");
                      return CachedNetworkImage(
                        cacheKey: _networklHasErrorNotifier.value.toString(),
                        imageUrl: "https://via.placeholder.com/350x150",
                        fit: BoxFit.fitWidth,
                        progressIndicatorBuilder:
                            (context, url, downloadProgress) => Container(
                          alignment: Alignment.center,
                          height: MediaQuery.of(context).size.height * 0.5,
                          width: MediaQuery.of(context).size.width,
                          child: CircularProgressIndicator(
                              value: downloadProgress.progress),
                        ),
                        errorWidget: (context, url, error) {
                          return Container(
                            alignment: Alignment.center,
                            height: MediaQuery.of(context).size.height * 0.5,
                            width: MediaQuery.of(context).size.width,
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              crossAxisAlignment: CrossAxisAlignment.center,
                              children: [
                                Icon(
                                  Icons.perm_scan_wifi,
                                  color: Colors.grey[600],
                                  size: 50,
                                ),
                                Padding(
                                  padding:
                                      const EdgeInsets.only(bottom: 20, top: 25),
                                  child: Text(
                                    'Failed To Load Image',
                                    style: TextStyle(
                                        color: Colors.white, fontSize: 17),
                                  ),
                                ),
                                Padding(
                                  padding: const EdgeInsets.only(
                                      bottom: 12.0, left: 10, right: 10),
                                  child: Text(
                                    'Check your internet connection and try again.',
                                    textAlign: TextAlign.center,
                                    style: TextStyle(color: Colors.grey),
                                  ),
                                ),
                                FlatButton(
                                  shape: RoundedRectangleBorder(
                                      borderRadius: BorderRadius.circular(8)),
                                  child: Text('Retry',
                                      style: TextStyle(color: Colors.black)),
                                  onPressed: () {
                                    print("clicked");
                                    _networklHasErrorNotifier.value++;
                                    //setState(() {});
                                  },
                                  //color: Pigment.fromString('#FFCC00'),
                                )
                              ],
                            ),
                          );
                        },
                      );
                    })
              ],
            ),
          ),
        );
      }
    }