失败时重新加载缓存的网络图像

Reload cached Network Image upon failure

对于在列表视图中显示的图像,我有 class。有时图像失败并且 setstate 不会重新加载图像,也没有任何我想到的方法有效,即使在分配唯一键值时也是如此。

图片classreturns这段代码:

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

能否请您提出一种在失败时重新加载图像的方法,我只能使用缓存的网络图像,没有其他包有用,因为我是唯一的缓存关键功能。

您可以复制粘贴运行下面的完整代码
您可以使用 ValueNotifier 更改 cacheKey of CachedNetworkImage
在工作演示中
第 1 步:图像未加载 airplane mode
第 2 步:关闭 airplane mode
第 3 步:然后单击 Retry button,然后单击 _networklHasErrorNotifier.value++
第 4 步:ValueListenableBuilder 用新的 cacheKey

重建 CachedNetworkImage

代码片段

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

工作演示

完整代码

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

我也是,当我的列表视图在列表项图像中一次又一次地重新加载时向上或向下滚动时遇到相同类型的问题。

最后,我在 ListViewBuilder 中添加 cacheExtent (int value) 参数,这个问题就解决了,

ListView.builder(
    cacheExtent: 9999,
    itemCount: snapshot.data.items.length,
    itemBuilder: (context, I) 
    {
       return getItemCard(
           child: CachedNetworkImage(
           imageUrl: snapshot.data.items[i],
           placeholder: (context, url) => CircularProgressIndicator(),
           errorWidget: (context, url, error) => Icon(Icons.error),
    ), 
  );
});