asynchronous - Flutter:从 Future 获取值(value)的正确方法

标签 asynchronous flutter dart async-await future

我有一个返回图像目录路径的函数,它执行一些额外的检查,比如目录是否存在,然后它会相应地运行。

这是我的代码:

Future<String> getImagesPath() async {
   final Directory appDir = await getApplicationDocumentsDirectory();
   final String appDirPath = appDir.path;

   final String imgPath = appDirPath + '/data/images';

   final imgDir = new Directory(imgPath);

   bool dirExists = await imgDir.exists();

   if (!dirExists) {
        await new Directory(imgPath).create(recursive: true);
   }

   return imgPath;

}

这段代码按预期工作,但我在从 Future 获取值(value)时遇到问题.

案例场景:
我将数据存储在本地数据库中并尝试在 ListView 中显示它。我正在使用 FutureBuilder ,如本 answer 中所述.每个数据行都有一个与之相连的图像(连接意味着,图像名称存储在db中)。

Widget build方法,我有这个代码:
@override
Widget build(BuildContext context) {
 getImagesPath().then((path){
     imagesPath = path;
     print(imagesPath); //prints correct path
   });
 print(imagesPath);   //prints null

return Scaffold(
    //removed
    body: FutureBuilder<List>(
        future: databaseHelper.getList(),
        initialData: List(),
        builder: (context, snapshot) {
          return snapshot.hasData
              ? ListView.builder(
                  itemCount: snapshot.data.length,
                  itemBuilder: (_, int position) {
                    final item = snapshot.data[position];
                    final image = "$imagesPath/${item.row[0]}.jpg";
                    return Card(
                        child: ListTile(
                      leading: Image.asset(image),
                      title: Text(item.row[1]),
                      subtitle: Text(item.row[2]),
                      trailing: Icon(Icons.launch),
                    ));
                  })
              : Center(
                  child: CircularProgressIndicator(),
                );
        }));

}

换挡return Scaffold(.....).then不起作用。因为小部件构建不返回任何内容。

我发现的另一个选项是 async/await但最后,同样的问题,代码如下:
_getImagesPath() async {
    return await imgPath();
}

调用 _getImagesPath()返回 Future , 而不是实际数据。

我相信有很小的逻辑错误,但我自己找不到。

最佳答案

我看到您必须从两个 future 的输出中构建您的小部件。您可以使用两个 FutureBuilders或者有一个辅助方法将它们组合成一个简化的代码单元。

另外,永远不要从 build 计算/调用异步函数功能。它必须事先初始化(在构造函数或 initState 方法中),否则小部件可能最终会永远重新绘制自己。

来到解决方案:为了简化代码,最好将两个 future 的输出组合到一个类中,如下例所示:
build 所需的数据方法:


class DataRequiredForBuild {
  String imagesPath;
  List items;

  DataRequiredForBuild({
    this.imagesPath,
    this.items,
  });
}

获取所有必需数据的函数:

Future<DataRequiredForBuild> _fetchAllData() async {
  return DataRequiredForBuild(
    imagesPath: await getImagesPath(),
    items: await databaseHelperGetList(),
  );
}

现在将所有内容放在 Widget 中:
Future<DataRequiredForBuild> _dataRequiredForBuild;

@override
void initState() {
  super.initState();
  // this should not be done in build method.
  _dataRequiredForBuild = _fetchAllData();
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    //removed
    body: FutureBuilder<DataRequiredForBuild>(
      future: _dataRequiredForBuild,
      builder: (context, snapshot) {
        return snapshot.hasData
            ? ListView.builder(
                itemCount: snapshot.data.items.length,
                itemBuilder: (_, int position) {
                  final item = snapshot.data.items[position];
                  final image = "${snapshot.data.imagesPath}/${item.row[0]}.jpg";
                  return Card(
                      child: ListTile(
                    leading: Image.asset(image),
                    title: Text(item.row[1]),
                    subtitle: Text(item.row[2]),
                    trailing: Icon(Icons.launch),
                  ));
                })
            : Center(
                child: CircularProgressIndicator(),
              );
      },
    ),
  );
}


希望能帮助到你。

关于asynchronous - Flutter:从 Future 获取值(value)的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58038475/

相关文章:

javascript - 如何禁止按下 "next"按钮,直到所有输入都更新

javascript - 如何用Node.js异步查询大量数据?

flutter - Flutter-DropdownButton onChanged返回null

c# - 这是异步调用同步方法的正确方法吗?

javascript - Typescript中异步函数的返回值

firebase - 如何从Firebase排序数据?在Flutter应用内

flutter : initial value not updating in Form (FormBuilder)

android - Flutter Swiper,带有小部件列表

dart - 控制台打印速度

flutter - 如何使用 Flutter 实现这个特定的滚动动画?