【问题标题】:Flutter FutureBuilder rebuilds unnecessarily when navigate between screens在屏幕之间导航时,Flutter FutureBuilder 会不必要地重建
【发布时间】:2021-01-28 19:11:06
【问题描述】:

在屏幕之间导航时,我的 FutureBuilder 会不必要地重建。每次我必须从 Firebase 存储中获取下载 URL 时,都会导致非常闪烁。每次在屏幕之间导航时,如何防止 FutureBuilder 重新构建?

我已经尝试了以下解决方案:

https://medium.com/saugo360/flutter-my-futurebuilder-keeps-firing-6e774830bc2

Flutter Switching to Tab Reloads Widgets and runs FutureBuilder

但没有成功。使用这两个 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());
              }
            }
          }),
    );
  }
}

我的期望

我希望在更改屏幕并返回初始屏幕后,我的图像仍然会出现,而无需重新加载。我正在为图像使用英雄动画。这种加载行为会破坏我的动画,因为在加载图像 url 时它会显示一个占位符。

一个小视频:(如果我推到详细信息屏幕并弹回初始屏幕,也会发生这种情况)

我能做些什么来解决这个问题?

【问题讨论】:

  • 请分享您的尝试。您似乎没有尝试过链接问题的答案。
  • 我已经通过两次尝试编辑了我的代码。谢谢你:)
  • 请分享两者的行为以及它是如何不受欢迎的。 没有办法停止构建。它们是 Flutter 正常运行所必需的。
  • 我再次编辑了我的问题,并提供了我期望的行为的附加信息。
  • 您对AutomaticKeepAliveClientMixin 的尝试在哪里?您需要分享更多代码。

标签: flutter dart flutter-futurebuilder


【解决方案1】:

我认为您需要在小部件树中走得更高,并保留页面的状态。您可以尝试this 解决方案。解决方案是使用PageView 小部件通过导航栏显示您的屏幕,而PageView 可以让您轻松保存页面状态。

【讨论】:

  • 但是如果我推送到另一个页面并返回到初始页面,Futurebuilder 也会重新构建。它不仅是底部导航..
  • 由于“PageView”,您的页面状态应该被保留。您将页面控制器分配给 pageview 小部件,并在页面控制器实例内将“保留页面”参数设置为 true。我认为这是最好的方法,试试这个解决方案
  • 只是一个额外的问题......例如,如果我更改了我正在使用 FutureBuilder 的对象的一些值怎么办?然后我想手动触发重建......使用 pageView 解决方案我永远拥有初始状态。有解决方法吗?非常感谢您!
  • 你可以设置未来本身
  • 谢谢,但是如何添加条件?默认情况下,我不希望未来的构建器重建,但前提是数据库中有更新......所以如果值发生变化......有没有最好的方法来解决这个问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-23
  • 1970-01-01
  • 2020-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多