0

我有一个Future,完成后,将一些数据添加到ChangeNotifierProvider. 然后我使用 ChangeNotifierProvider 中的数据来填充一些ListViews. 问题是,我有 2 个屏幕,它们都从同一个 Future 获取他们需要的数据。每个屏幕都有一个返回 ListView 的 FutureBuilder。 如何让 2 个 FutureBuilders 等待“相同”的未来,而不调用它 2 次? FutureProvider 是解决方案吗?

4

1 回答 1

0

您应该使用Future.waitAPI,它的作用是等到所有期货都完成并返回其结果或错误。

将此视为示例:

  Future<String> getData() async {
    final future1 = Future<String>.delayed(Duration(seconds: 1), () => "I am");
    final future2 = Future<int>.delayed(Duration(seconds: 2), () => 100);
    final future3 = Future<String>.delayed(Duration(seconds: 3), () => "Years old!");
    final results = await Future.wait([future1, future2, future3]);

    // Doing a simple cast considering my Future will never fails in this example, you should check for exceptions/errors!
    final future1ResultOrError = results.first as String;
    final future2ResultOrError = results[1] as int;
    final future3ResultOrError = results[2] as String;
    return "$future1ResultOrError $future2ResultOrError $future3ResultOrError";
  }

您可以像使用单个 Future 一样使用它:

            FutureBuilder(
              future: getData(),
              initialData: null,
              builder: (context, shot) {
                return Text(shot.hasData ? shot.data : "Waiting for data...");
              },
            ),

这将打印:“我已经 100 岁了!”。注意它是如何从不同的期货加载数据的!

编辑:

您可能希望拥有一个 Future 并将其提供给两个 FutureBuilder。见下面的代码:

class _MyState extends State<MyPage> {

  Future mySingleFuture;

  Future<String> getData() async {
    final future1 = Future<String>.delayed(Duration(seconds: 1), () => "I am");
    final future2 = Future<int>.delayed(Duration(seconds: 2), () => 100);
    final future3 = Future<String>.delayed(Duration(seconds: 3), () => "Years old!");
    final results = await Future.wait([future1, future2, future3]);

    // Doing a simple cast considering my Future will never fails in this example, you should check for exceptions/errors!
    final future1ResultOrError = results.first as String;
    final future2ResultOrError = results[1] as int;
    final future3ResultOrError = results[2] as String;
    return "$future1ResultOrError $future2ResultOrError $future3ResultOrError";
  }

  @override
  void initState() {
    super.initState();
    mySingleFuture = getData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            FutureBuilder(
              future: getData(),
              initialData: null,
              builder: (context, shot) {
                return Text(shot.hasData ? shot.data : "Waiting for data...");
              },
            ),
            FutureBuilder(
              future: getData(),
              initialData: null,
              builder: (context, shot) {
                return Text(shot.hasData ? shot.data : "Waiting for data 2...");
              },
            ),
          ],
        ),
      ),
    );
  }
}
于 2020-12-30T12:49:45.100 回答