【问题标题】:Is there a way for multiple FutureBuilders to use the same future from a ChangeNotifier?有没有办法让多个 FutureBuilders 使用 ChangeNotifier 中的同一个未来?
【发布时间】:2019-12-30 23:01:16
【问题描述】:

我有一个类(扩展 ChangeNotifier - Provider 包),它有一个返回 Future 的函数。我想要做的是拥有它,以便我的 UI 代码中的多个 futureBuilder 可以从该函数接收值,但不必为每个 FutureBuilder 调用该函数一次。

但是,我使用的每个 FutureBuilder 都会一次又一次地运行该函数本身。我知道必须有一种方法可以通过 Provider 包公开 Future 本身,但我似乎无法弄清楚如何。

这是扩展 ChangeNotifier 并拥有未来的类:

class ApiService extends ChangeNotifier {

  CurrencyTicker _data;

  CurrencyTicker get getdata => _data;

  set setdata(CurrencyTicker data) {
    _data = data;
  }

  Future<CurrencyTicker> fetchBaseData() async {
    final response =
    await http.get(API_URL_HERE); // url removed for stackoverflow

    if (response.statusCode == 200) {
    print('1 call logged');
    setdata =  CurrencyTicker.fromJson(json.decode(response.body));
    return CurrencyTicker.fromJson(json.decode(response.body));
    } else {
    throw Exception('Request failed: ' + response.statusCode.toString());
    }
  }
}

这是 UI 代码(它只是一个 FutureBuilder):

class MyBody extends StatelessWidget {
  const MyBody({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final provider = Provider.of<ApiService>(context);

    return Center(
      child: FutureBuilder(
        future: provider.fetchBaseData(),
        initialData: CurrencyTicker().price,
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            return Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                Text(snapshot.data.company),
              ],
            );
          } else {
            return LinearProgressIndicator();
          }
        },
      ),
    );
  }
}

我没有在小部件树的“顶层”包含 MultiProvider,因为我不明白为什么必须这样做。我没有包含 CurrencyTicker 类的模型。如果需要,我可以提供这两个。

非常感谢您的任何意见

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    您不想直接在消费者的 build 方法中进行 HTTP 调用。

    您应该公开一个属性,而不是在 ChangeNotifier 上公开一个方法:

    class MyNotifier with ChangeNotifier {
      Future<Foo> foo;
    }
    

    foo 是一个变量,用于存储您上次调用 fetchData 的结果。

    根据您的需要,您可以:

    • 如果立即需要,请在构造函数中调用 fetchData
    class MyNotifier with ChangeNotifier {
      MyNotifier() {
        foo = fetchData();
      }
      Future<Foo> foo;
    }
    
    • 使用自定义 getter 延迟加载:
    class MyNotifier with ChangeNotifier {
      Future<Foo> _foo;
      Future<Foo> get foo => _foo ??= fetchData();
    }
    

    【讨论】:

    • 如果您使用流执行此操作,请确保将其设为广播流以避免错误:` foo = fetchData().asBroadcastStream(); `
    猜你喜欢
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    • 2015-03-20
    • 2012-03-08
    • 1970-01-01
    • 2016-03-31
    相关资源
    最近更新 更多