flutter_cached_network_image
flutter_cached_network_image copied to clipboard
Reload an image from network after error?
💬 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?
Just go back to version 2.2.0
I have a similar issue:
- User navigates to Profile where image is show for the first time - image is not found (404 network error), placeholder is shown.
- User uploads new image.
- 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.
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.
I did not. But in my case image was never loaded (404), so why cache that?
In cases where the image is never loaded, this probably wont help.
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.
Same issue here
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.
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.
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,
),
),
);
}
}
absolutely same here. ios app stops responding any network call.
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(),
),
);
},
);
}
}