在屏幕之间导航时,Flutter FutureBuilder 会不必要地重建
Flutter FutureBuilder rebuilds unnecessarily when navigate between screens
在屏幕之间导航时,我的 FutureBuilder 会进行不必要的重建。每次我都必须从 Firebase 存储中下载 URL,这会导致极度闪烁。如何防止 FutureBuilder 每次在屏幕之间导航时重建?
我已经尝试过以下解决方案:
https://medium.com/saugo360/flutter-my-futurebuilder-keeps-firing-6e774830bc2
但是没有成功。使用 FutureBuilder 总是重建。
这是我的代码(尝试 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());
}
}
}),
);
}
}
尝试 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());
}
}
}),
);
}
}
我期待的
我希望在更改屏幕和 return 到初始屏幕后,我的图像仍然显示而无需重新加载。我正在为图像使用英雄动画。这种加载行为破坏了我的动画,因为在加载图像 url 时它显示了一个占位符。
一个小视频看起来如何:(如果我按到详细信息屏幕并弹出回到初始屏幕,也会发生这种情况)
我该怎么做才能解决这个问题?
我认为您需要在小部件树中走得更高,并保留页面的状态。您可以尝试 解决方案。解决方案是使用 PageView
小部件通过导航栏显示您的屏幕,并且 PageView
允许您轻松保存页面状态。
在屏幕之间导航时,我的 FutureBuilder 会进行不必要的重建。每次我都必须从 Firebase 存储中下载 URL,这会导致极度闪烁。如何防止 FutureBuilder 每次在屏幕之间导航时重建?
我已经尝试过以下解决方案:
https://medium.com/saugo360/flutter-my-futurebuilder-keeps-firing-6e774830bc2
但是没有成功。使用 FutureBuilder 总是重建。
这是我的代码(尝试 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());
}
}
}),
);
}
}
尝试 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());
}
}
}),
);
}
}
我期待的
我希望在更改屏幕和 return 到初始屏幕后,我的图像仍然显示而无需重新加载。我正在为图像使用英雄动画。这种加载行为破坏了我的动画,因为在加载图像 url 时它显示了一个占位符。
一个小视频看起来如何:(如果我按到详细信息屏幕并弹出回到初始屏幕,也会发生这种情况)
我该怎么做才能解决这个问题?
我认为您需要在小部件树中走得更高,并保留页面的状态。您可以尝试 PageView
小部件通过导航栏显示您的屏幕,并且 PageView
允许您轻松保存页面状态。