My FutureBuilder rebuilds unnecessarily when navigate between screens. Each time I have to get the download URL from the Firebase Storage and this results in extremely flickering. How can I prevent that the FutureBuilder rebuilds everytime I navigate between screens?
I already tried the following solutions:
https://medium.com/saugo360/flutter-my-futurebuilder-keeps-firing-6e774830bc2
Flutter Switching to Tab Reloads Widgets and runs FutureBuilder
But without success. With both the FutureBuilder get always rebuild.
This is my code (Attempt 1):
class _GuestbookCardImageState extends State<GuestbookCardImage> {
final AsyncMemoizer _memoizer = AsyncMemoizer();
_getFeaturedImages() {
return this._memoizer.runOnce(() async {
return await MyStorage().getDownloadUrl(widget.guestbook.imagePath);
});
}
@override
Widget build(BuildContext context) {
return Card(
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 2,
margin: EdgeInsets.all(5),
child: FutureBuilder(
future: _getFeaturedImages(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return GuestbookPlaceholder();
} else {
if (snapshot.data != null) {
return Hero(
tag: "to_single_guestbook_" + widget.guestbook.entryCode,
child: Container(
width: Get.width / 1.7,
height: Get.height / 3.5,
child: Image.network(
snapshot.data,
fit: BoxFit.cover,
),
),
);
} else {
return Hero(
tag: "to_single_guestbook_" + widget.guestbook.entryCode,
child: GuestbookPlaceholder());
}
}
}),
);
}
}
Attempt 2
class _GuestbookCardImageState extends State<GuestbookCardImage> {
Future<String> _future;
@override
void initState() {
_future = MyStorage().getDownloadUrl(widget.guestbook.imagePath);
super.initState();
}
@override
Widget build(BuildContext context) {
return Card(
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 2,
margin: EdgeInsets.all(5),
child: FutureBuilder(
future: _future,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return GuestbookPlaceholder();
} else {
if (snapshot.data != null) {
return Hero(
tag: "to_single_guestbook_" + widget.guestbook.entryCode,
child: Container(
width: Get.width / 1.7,
height: Get.height / 3.5,
child: CachedNetworkImage(
imageUrl: snapshot.data, fit: BoxFit.cover),
),
);
} else {
return Hero(
tag: "to_single_guestbook_" + widget.guestbook.entryCode,
child: GuestbookPlaceholder());
}
}
}),
);
}
}
What I expect
I expect that after changing the screen and return to the initial screen my images still appearing without the need of reload. I am using Hero animation for the images. This loading behavior destroys my animation because while loading the image urls it shows a placeholder.
A small video how this looks: (And this happens also if I push to the detail screen and pop back to the initial screen)
What could I do to solve this issue?
I think you need to go higher in the widget tree and preserve the state of your page. you can try this solution. The solution is to use PageView
widget to display your screen through the navigation bar, and the PageView
allowing you to save the page state easily.