flutter - Flutter/Dart:获取目录内容但未来不工作
问题描述
我正在尝试获取目录的内容并将其显示在屏幕上。
当我只有 1 个未来(并在方法中硬编码返回值)时,我能够显示它们。但是当我在未来中嵌入未来时(我需要这样做以获取应用程序目录和文件列表),它不起作用。
这是我的代码:
Future<List<CardFileInfo>> _getFilelist() {
var localFileHelper = new LocalFileHelper();
return Future.value(localFileHelper.getFileList());
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Cards")
),
body: Center(
child: Column(
children: <Widget>[
FutureBuilder<List<CardFileInfo>>(
future: _getFilelist(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text("Files Found");
}
else {
return Text("Still looking");
}
} //end of builder
), //end of future builder
], //end of children
), //end of column
), //end of center
); //end of scaffold
}
下面是 localFileHelper.getFileList() 方法的代码:
List<CardFileInfo> getFileList() {
List<CardFileInfo> cardInfoList = [];
final dirName = getApplicationDocumentsDirectory();
// *** if I uncomment the following two lines, the process works ***
// cardInfoList.add(CardFileInfo("dummy.tsv"));
// return cardInfoList;
dirName.then((dir) { // <---------- problem seems occurs here with the future
final files = dir.list().toList();
files.then((values){
values.forEach((element) {
var type = element.path.toString().split(".").last.trim();
if (type == "tsv") {
var currCard = CardFileInfo(element.path.toString().trim());
cardInfoList.add(currCard);
}
}); //end of foreEach
return cardInfoList;
}); //end of files.then
}); //end of dirName.then
} //end of getFileList()
当我单步执行代码时,“返回文本(”仍在寻找“);” 行最多执行两次。
该函数最终返回该值,但似乎 FutureBuilder 没有等待足够长的时间来返回该值。
我是 Flutter 和 Dart 的新手,这个问题真的让我很困惑。
解决方案
您对问题发生位置的直觉是正确的;它发生在.then
通话中。发生这种情况的原因是因为.then
立即返回(它是“非阻塞的”),因此该方法将立即返回。Future 将在没有附加值的情况下完成,因为.then
调用不会完成。在将来的某个时候,应该填充列表,但您将不知道何时使用当前方法。
我可以想到三种解决方案来解决这个问题:
- (我会推荐这种方法)使用
async/await
关键字使您的方法更容易异步。我不能保证这会按原样工作(自从我处理 Dart/Flutter 以来已经有几个月了),所以一些语法可能是错误的,但想法就在那里。
Future<List<CardFileInfo>> getFileList() async {
List<CardFileInfo> cardInfoList = [];
final dirName = await getApplicationDocumentsDirectory();
final files = await dirName.list().toList();
for (final element in files) {
final type = element.path.toString().split(".").last.trim();
if (type == "tsv") {
final currCard = CardFileInfo(element.path.toString().trim());
cardInfoList.add(currCard);
}
}
return cardInfoList;
} //end of getFileList()
- 使用
Completer
. 这给了你更多的控制权,但在这种情况下我不推荐它,因为它需要样板文件并且会在这里有点损害可读性。 initState
在将填充列表的 a中调度调用StatefulWidget
,然后setState
在获取完成时使用调用来更新 UI。
推荐阅读
- java - 如何在 Java 或 Kotlin 中用我自己的注释包装 @Column 注释
- wagtail - Wagtail Form 静态字段和仅限超级用户的页面
- gitlab-ci - 带有 kustomize 的 ArgoCD 在运行时替换图像
- python - 我不断从抓取的网站获得太多链接
- python - 在python中计算FWHM
- javascript - 创建一个单例对象以跨不同页面保存数据
- javascript - 未能对存储在 localStorage 中的对象调用构造函数方法
- c# - 如何在不冻结应用程序 xamarin 表单的情况下添加很多孩子
- python - 在本地安装带有 pip3 的 python 包而不是以 root 身份安装 python 包时的 Python coredumps
- python - OpenCV 在我的 macOS 上安装后无法工作。谁能帮我吗?