在屏幕之间导航时,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 允许您轻松保存页面状态。