How to load network image in Flutter with retry functionality.

Mohit Gupta
2 min readFeb 25, 2024

--

Photo by Franck on Unsplash

In this article, we will go through the steps that should be followed when loading an image from the network in Flutter. Before delving into the solution, let’s examine the problem we’re encountering.

The article mentioned addresses the issue on the Crashlytics side. However, the problem persists as the image still fails to load.

How to load image for network.

Image.network(
'https://i.ytimg.com/vi/4qlScPdIoio/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDuKfsOtA_DA2utq4NcodnfNGOlWA',
fit: BoxFit.fill,
)

How load image from network with retry on failure and tap to reload feature.

Image.network(
'htt://i.ytimg.com/vi/4qlScPdIoio/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDuKfsOtA_DA2utq4NcodnfNGOlWA',
fit: BoxFit.fill,
errorBuilder: (context, error, stackTrace) {
if (retryAttempt > 0) {
retryAttempt--;
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {});
});
}
return InkWell(
onTap: () {
setState(() {});
},
child: const Icon(Icons.error),
);
},
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,
),
);
},
)

In this approach, if the loading of an image fails initially, the system will attempt to load it repeatedly until it reaches the retry threshold. Subsequently, the user can tap on the error widget, which will be displayed in case of a failure, to reload the image.

Happy coding!
Mohit Gupta
Flutter Developer
GitHub Profile

Source Code

import 'package:flutter/material.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}

class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});

@override
State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
int retryAttempt = 5;

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Image.network(
'http://i.ytimg.com/vi/4qlScPdIoio/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDuKfsOtA_DA2utq4NcodnfNGOlWA',
fit: BoxFit.fill,
errorBuilder: (context, error, stackTrace) {
if (retryAttempt > 0) {
retryAttempt--;
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {});
});
}
return InkWell(
onTap: () {
setState(() {});
},
child: const Icon(Icons.error),
);
},
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,
),
);
},
),
),
);
}
}

--

--