您如何将将来的列表转换为用作变量而不是窗口小部件的列表?

时间:2018-11-13 19:50:14

标签: dart flutter future

我正在尝试实现PaginatedDataTable类。该类的构造函数中的必填字段是类DataTableSource。查看flutter画廊示例here的材料部分中的数据表示例。 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()返回了Future。如果我将返回类型更改为将来的类型,results确实可以编译,但是我需要将返回的json类型设为List,以便可以使用sort等方法。应该如何转换未来的清单。

1 个答案:

答案 0 :(得分:2)

在您的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>,当它是一个硬编码值时,您可以像以前一样使用它。

修改:

如果您不想使用FutureBuilder,则建议您使用一个函数,该函数可以在http调用完成时基本上修改results的值。这是我的意思的示例:

DessertDataSource在其构造函数中使用List<Result>来定义results的值,如下所示:

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

_DataTableDemoState中,使_dessertsDataSource不再是最终的,并将其初始值更改为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调用返回数据时,小部件都会自动使用新数据进行更新。