我有以下代码:
class FileData {
Future<String> get _localPath async {
print('D: Local'); //D
final directory = await getApplicationDocumentsDirectory();
print('D: Directory: $directory'); //D
return directory.path;
}
Future<File> get _localFile async {
final path = await _localPath;
print('D: Path: $path'); //D
return File('$path/file.dat');
}
Future<File> _future;
Future<RandomAccessFile> _futureRandomAccessFile;
File _file;
RandomAccessFile _randomAccessFile;
FileData() {
print('D: First'); //D
_future = _localFile;
_future = _future.then(
(File file) {
print('D: Stuff'); //D
if(file == null) throw 'file == null';
_file = file;
print('D: Foo'); //D
_futureRandomAccessFile = file.open(mode: FileMode.append);
_futureRandomAccessFile = _futureRandomAccessFile.then(
(RandomAccessFile randomAccessFile) {
if(randomAccessFile == null) throw 'randomAccessFile == null';
_randomAccessFile = randomAccessFile;
print('D: Position: ${_randomAccessFile.positionSync()}'); //D
int byte = DateTime.now().second; //D
print('D: Write: $byte'); //D
_randomAccessFile.writeByte(byte); //D
return randomAccessFile;
},
onError: (e) {
throw e;
}
).timeout(Duration(seconds: 2));
return file;
},
onError: (e) {
print('D: Bad'); //D
throw e;
}
).timeout(Duration(seconds: 2));
}
_syncRandomAccessFile() {
while(_randomAccessFile == null) {
print('Waiting on _randomAccessFile...');
}
}
void close() {
_syncRandomAccessFile();
print('D: Position: ${_randomAccessFile.positionSync()}'); //D
_randomAccessFile.setPositionSync(0); //D
print('D: Position: ${_randomAccessFile.positionSync()}'); //D
print('D: Byte: ${_randomAccessFile.readByteSync()}'); //D
int byte = DateTime.now().second; //D
print('D: Write: $byte'); //D
_randomAccessFile.writeByte(byte); //D
_randomAccessFile.close();
_randomAccessFile = null;
}
}
FileData fileData;
这在我的应用首页状态:
@override
void initState() {
super.initState();
fileData = FileData();
sleep(Duration(seconds: 1));
fileData.close();
}
我希望发生以下事件:
D: First
D: Local
(some or none) Waiting on _randomAccessFile...
D: Directory: <whatever>
D: Path: <whatever>
D: Stuff
D: Foo
(some or none) Waiting on _randomAccessFile...
D: Position: <whatever>
D: Write: <whatever>
D: Position: <whatever>
D: Position: 0
D: Byte: <whatever>
D: Write: <whatever>
相反,我得到了:
D: First
D: Local
(a lot of) Waiting on _randomAccessFile...
(app freezes)
我不明白为什么会这样。我显然需要在读取/写入/关闭文件之前将其打开,并且我需要在一个实例变量中使其能够在同步和异步代码中使用。我的理解是,getApplicationDocumentsDirectory()
返回的未来由于某种原因永远不会完成。
我希望这是我所遇到的一些基本误会,比其他任何事情都重要。
答案 0 :(得分:1)
您的sleep
调用不符合您的期望,因为它不允许运行异步操作。
按持续时间指定的持续时间进行睡眠。
请谨慎使用此选项,因为在睡眠调用中阻塞异步操作后,无法单独处理任何异步操作。
https://api.flutter.dev/flutter/dart-io/sleep.html
此外,在构造函数内部进行异步操作也不是一个好主意,因为您无法确定何时完全创建对象。相反,请在FileData
内创建一个静态方法,该方法可以返回Future<FileData>
,目的是在返回完全构造的对象之前执行所有异步操作。这样,您无需sleep
。
答案 1 :(得分:0)
julemand101的评论给出了这个问题的答案。万一有人发现这个问题,并正在寻找我从中学到的详细解释...
Dart是单线程的。仅当当前操作完成并且控制返回到事件循环时,异步操作才完成。 await
以某种方式确保发生这种情况。如果我将fileData.close()
放在事件循环调用的另一个函数中,也会发生这种情况。但是我打电话给构造函数,然后等待将来完成,而又没有将控制权交还给它们之间的事件循环,所以将来永远不会完成,并且永远锁定着。