首页 > 解决方案 > 您如何将列表未来转换为列表以用作变量而不是小部件?

问题描述

我正在尝试PaginatedDataTable在颤振中实现该类。此类的构造函数中的必需字段是 class DataTableSource在此处查看颤振库示例的材料部分中的数据表示例。DataTableSource 有一个成员变量List<Dessert> _desserts,它的值是硬编码的。在我的实现中,我正在进行 http 调用并返回一些要解码的 json。

List<Result> parseResults(String responseBody) {
  final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();

  return parsed.map<Result>((json) => Result.fromJson(json)).toList();
}

Future<List<Result>> fetchResults(http.Client client) async {
  final response = await client.get('https://api.myjson.com/bins/j5xau');

  // Use the compute function to run parseResults in a separate isolate
  return compute(parseResults, response.body);

在我的 DataTableSource 类中,我不确定如何实例化列表。

`final List<Result> results = fetchResults(http.Client);` 

不编译,因为fetchResults()返回一个未来。如果我将返回类型更改为未来,则results确实可以编译,但我需要返回的 json 是类型List,以便我可以使用诸如sortetc 之类的方法。我应该如何将未来转换为列表。

标签: dartflutterfuture

解决方案


在您的DataTableSource班级中,只需删除该results变量。然后在你的build函数中,你可以使用这样的FutureBuilder小部件:

FutureBuilder<List<Result>>(
  future: fetchResults(http.Client), 
  builder: (BuildContext context, AsyncSnapshot<List<Result>> snapshot) {
    switch (snapshot.connectionState) {
      case ConnectionState.none:
        return Text('Press button to start.');
      case ConnectionState.active:
      case ConnectionState.waiting:
        return Text('Awaiting result...');
      case ConnectionState.done:
        if (snapshot.hasError)
          return Text('Error: ${snapshot.error}');
        return Text('Result: ${snapshot.data}');
    }
    return null; // unreachable
  },
)

请注意,这snapshot.data是一个List<Result>现在,您可以像在硬编码值时使用它一样使用它。

编辑:

如果您不想使用 aFutureBuilder我建议您使用一个函数,该函数基本上会在resultshttp 调用完成时修改 的值。这是我的意思的一个例子:

在其构造函数DessertDataSource中使用 aList<Result>来定义如下的值results

class DessertDataSource extends DataTableSource {
  final List<Result> results;
  DessertDataSource(this.results);
  // rest of the class
}

在 中_DataTableDemoState,使 _dessertsDataSource不再是 final 并将其初始值更改为DessertDataSource([])。此外,添加一个布尔值,指示数据何时已加载或未加载。

class _DataTableDemoState extends State<DataTableDemo> {
  // other fields!
  DessertDataSource _dessertsDataSource = DessertDataSource([]);
  bool isLoaded = false;

然后将以下函数添加到_DataTableDemoState. 布尔值确保我们只进行一次 http 调用。

Future<void> getData() async {
  final results = await fetchResults(http.Client);
  if (!isLoaded) {
      setState(() {
        _dessertsDataSource = DessertDataSource(results);
        isLoaded = true;
      });
  }
}

最后在按下按钮或其他触发器时调用该函数,或者可能只是在构建函数的开头。

@override
Widget build(BuildContext context) {
    getData();
    return MYWidget();
}

然后,每当从 http 调用返回数据时,小部件将使用新数据自动更新。


推荐阅读