首页 > 解决方案 > 有没有办法让多个 FutureBuilders 使用 ChangeNotifier 中的同一个未来?

问题描述

我有一个类(扩展 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 类的模型。如有必要,我可以提供这两个。

将不胜感激任何意见在这里

标签: flutterdart

解决方案


您不想直接在使用者的 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();
}

推荐阅读