Flutter FutureBuilder在屏幕之间导航时不必要地重建

时间:2020-10-14 11:29:34

标签: flutter dart flutter-futurebuilder

在屏幕之间导航时,我的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());
              }
            }
          }),
    );
  }
}

我期望的结果

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

一个小视频,看起来像:(而且如果我按到详细信息屏幕并弹出回到初始屏幕,也会发生这种情况)

enter image description here

我该怎么做才能解决这个问题?

1 个答案:

答案 0 :(得分:2)

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