首页 > 解决方案 > 在 Flutter 中切换页面时如何保持 Future 的值?

问题描述

当未来在屏幕 1 中有数据时,我正在尝试向屏幕添加一个小部件。

class UserChoiceBooks extends StatelessWidget {
  final String title;
  UserChoiceBooks({Key key, this.title}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
        future: Provider.of<Books>(context, listen: false)
            .getRecommendedBooks("test"),
        builder: (ctx, snapshot) {
          // Checking if future is resolved
          if (snapshot.connectionState == ConnectionState.done) {
            // If we got an error
            if (snapshot.hasError) {
              return Center(
                child: Text(
                  '${snapshot.error} occured',
                  style: TextStyle(fontSize: 18),
                ),
              );
              // if we got our data
            } else if (snapshot.hasData) {
              // Extracting data from snapshot object
              final List<Book> recommendedBooksML = snapshot.data;
              return BookList(title, recommendedBooksML);
            } else {
              return SizedBox.shrink();
            }
          } else {
            return Container();
          }
        }
        //  ... some code here
        );
  }
}

我导航到另一个屏幕屏幕 2。然后返回屏幕 1。我丢失了未来的数据,它再次开始构建。

PS:我通过将未来数据存储在全局变量中找到了一个临时解决方法 List<Book> placeholder=[];

然后从未来设置值......placeholder=snapshot.data;

在屏幕 1 和 2 之间切换时。我正在检查 placeholder==[]?UserChoiceBooks (title):BookList(title,placeholder)

有没有更好的方法来保留快照中的数据,以便在屏幕未来值之间切换不会丢失?

标签: flutterflutter-futurebuilder

解决方案


您在构建期间拨打电话:

Provider.of<Books>(context, listen: false).getRecommendedBooks("test")

因此,当屏幕重建时,它会再次被调用。你太幸运了,这两个导航之间没有发生其他重建,因为理论上它们是可能的。

推荐的心态是重建可能发生在每一帧,非重建帧应被视为框架优化。

因此,您应该拨打一次电话并保存。有几个选项:

  1. 在树的某处创建Books并将其传递给小部件。然后让你的小部件有状态并调用widget.books.getRecommendedBooks它的initState().

  2. 如果Books是单例,您可以使用像https://pub.dev/packages/get_it这样的服务定位器来实例化它一次,然后用于GetIt.instance.get在您的小部件中的任何位置获取此实例。服务定位器模式比提供者模式有一些优势。

  3. 一种讨厌的方法是在有状态小部件的状态下调用未来,并在首次构建时调用该方法 if _future == null

对于有状态的小部件,请参阅本教程:https ://flutter.dev/docs/development/ui/interactive#stateful-and-stateless-widgets

另请注意,您应该将 a用于这样的小部件,对于传递给构造函数key的不同 s 将有所不同。title否则,当您将您的小部件替换为另一个title时,框架将不知道接下来的所有内容都是针对另一本书的,并且不会创建新状态,因此initState()不会被调用。


推荐阅读