flutter_cached_network_image icon indicating copy to clipboard operation
flutter_cached_network_image copied to clipboard

Reload an image from network after error?

Open Paulabn opened this issue 4 years ago • 12 comments

💬 Questions and Help

Please advice if I am doing something wrong.

I create a CachedNetworkImageProvider and use it in an Image. In case there is a network error (lost connectivity), I use a certain placeholder instead of an image. What I want do next, is to try to reload an image upon some user action, and, if the connection is up again, actually load an image. To do that I create a new CachedNetworkImageProvider for rebuilding an Image, but it doesn't work. Calling the resolve method just immediately throws the same error as before (host not found), even not bothering to try it again. What I discovered then is that CachedNetworkImageProvider's instance hash is derived from the link and the scale values, and that's it. It seems that if I create a new CNIP with the same arguments as before, it is actually not really a new one. But if I modify the link in any way, viola! It loads the image as expected.

Please help me to understand if I am misusing the library, or if it is an intended behaviour after all?

Paulabn avatar Sep 13 '20 16:09 Paulabn

Just go back to version 2.2.0

amd110 avatar Sep 26 '20 09:09 amd110

I have a similar issue:

  1. User navigates to Profile where image is show for the first time - image is not found (404 network error), placeholder is shown.
  2. User uploads new image.
  3. New image is not shown, there is still a placeholder.

It will be show eventually (after app restart or going back and that again to Profile), but not right up after error and new upload.

Works perfectly on version 2.2.0+1.

liri2006 avatar Sep 28 '20 19:09 liri2006

Have you tried removing that particular image from the cache? afaik if the loading is interrupted, the cache will break and the image will never load until the cache is cleared.

clragon avatar Oct 02 '20 16:10 clragon

I did not. But in my case image was never loaded (404), so why cache that?

liri2006 avatar Oct 02 '20 17:10 liri2006

In cases where the image is never loaded, this probably wont help.

clragon avatar Oct 02 '20 17:10 clragon

I have modified the library by simply adding a third value to int get hashCode => hashValues(url, scale, myvalue) of CachedNetworkImageProvider, which I explicitly pass to it. Just passing a different one every time makes it reload the image. Maybe ugly, maybe I even don't fully understand why, but it gets the job done for me.

Paulabn avatar Oct 02 '20 17:10 Paulabn

Same issue here

sayhicoelho avatar Nov 13 '20 16:11 sayhicoelho

add a key on the CachedNetworkImage widget may help (it worked on my case).

 key: ValueKey<String>(url),

it forcibly recreates a new widget (state) when the URL changed.

Peng-Qian avatar Nov 23 '20 11:11 Peng-Qian

Hi, I have a similar use-case:

  • Image data is not present in the cache
  • Request fires, results in a 403 http response (ultimately because the URL expired)
  • HttpExceptionWithStatus is thrown from flutter_cache_manager

How such exception can be catched and properly handled (e.g. obtain a new url, retry, ...)?

May be related to #504.

RomainFranceschini avatar Dec 11 '20 09:12 RomainFranceschini

Here is my workaround: When image load was successful, we pass to key parameter of CircularProgressIndicator a constant value(in my case it's image url). When for some reason image was not loaded we pass to key parameter a dynamic value(DateTime.now().toString()), so that way we recreate the widget(because old key does not correspond to new one).

class PlotAttachmentImage extends StatefulWidget {
  static const kDefaultImageSize = 98.0;

  final double size;
  final double borderRadius;
  final Attachment attachment;

  final GestureTapCallback onTap;

  const PlotAttachmentImage({
    @required this.attachment,
    Key key,
    this.onTap,
    this.borderRadius = 2,
    this.size = kDefaultImageSize,
  }) : super(key: key);

  @override
  _PlotAttachmentImageState createState() => _PlotAttachmentImageState();
}

class _PlotAttachmentImageState extends State<PlotAttachmentImage> {
  bool successLoad = true;
  @override
  Widget build(BuildContext context) {
    return ClipRRect(
      borderRadius: BorderRadius.circular(widget.borderRadius),
      child: InkWell(
        onTap: widget.onTap,
        child: CachedNetworkImage(
                key: ValueKey<String>(
                  successLoad
                      ? widget.attachment.url.full
                      : DateTime.now().toString(),
                ),
                height: widget.size,
                width: widget.size,
                imageUrl: widget.attachment.url.full,
                progressIndicatorBuilder: (context, url, progress) {
                  successLoad = progress.downloaded == progress.totalSize;
                  return const CircularProgressIndicator();
                },
                errorWidget: (_, __, dynamic ___) {
                  return IconButton(
                    icon: const Icon(Icons.refresh),
                    onPressed: () => setState(() {}),
                  );
                },
                fit: BoxFit.cover,
              ),
      ),
    );
  }
}

radomir9720 avatar Mar 03 '21 14:03 radomir9720

absolutely same here. ios app stops responding any network call.

KanybekMomukeyev avatar Apr 18 '22 08:04 KanybekMomukeyev

Here is my workaround, regenerate a CachedNetworkImage via ValueNotifier

class _ExtendedNetworkImageState extends State<ExtendedNetworkImage> {
  final _rebuildValueNotifier = ValueNotifier('');

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<String>(
      valueListenable: _rebuildValueNotifier,
      builder: (context, value, child) {
        return CachedNetworkImage(
          key: value.isEmpty ? null : ValueKey(value),
          imageUrl: widget.imageUrl,
          fit: widget.fit,
          width: widget.width,
          height: widget.height,
          errorWidget: (context, url, error) => TryAgainIconExceptionIndicator(
            onTryAgain: () => _rebuildValueNotifier.value = const Uuid().v1(),
          ),
        );
      },
    );
  }
}

lauglam avatar Jun 13 '22 06:06 lauglam