【问题标题】:Stream and Future in DartDart 中的 Stream 和 Future
【发布时间】:2019-09-10 20:33:04
【问题描述】:

我一直在使用基本的 async/await 一段时间,没有遇到很多问题,我想我理解它是如何工作的。不能说我是这方面的专家,但我了解它的要点。不过,我只是无法理解 Streams。在今天之前,我以为我了解它们是如何工作的(基本上是响应式编程),但我无法让它们在 Dart 中工作。

我正在开发一个可以保存和检索 (json) 文件的持久层。我一直使用fileManager example 作为指导。

import 'dart:io';
import 'dart:async';
import 'package:intl/intl.dart'; //date
import 'package:markdowneditor/model/note.dart';//Model
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p;
import 'package:flutter/foundation.dart'; //log
import 'package:simple_permissions/simple_permissions.dart';//OS permissions

class FileManager {
  static final FileManager _singleton = new FileManager._internal();

  factory FileManager() {
    return _singleton;
  }

  FileManager._internal();

  Future<String> get _localPath async {
    final directory = (await getApplicationDocumentsDirectory()).toString();
    return p.join(directory, "notes"); //path takes strings and not Path objects
  }

  Future<File> writeNote(Note note) async {
    var file = await _localPath;
    file = p.join(
        file,
        DateFormat('kk:mm:ssEEEMMd').format(DateTime.now()) +
            " " +
            note.title); //add timestamp to title
    // Write the file

    SimplePermissions.requestPermission(Permission.WriteExternalStorage)
        .then((value) {
      if (value == PermissionStatus.authorized) {
        return File(file).writeAsString('$note');
      } else {
        SimplePermissions.openSettings();
        return null;
      }
    });

  }

  Future<List<Note>> getNotes() async {
    //need file access permission on android. use https://pub.dartlang.org/packages/simple_permissions#-example-tab-
    final file = await _localPath;

    SimplePermissions.requestPermission(Permission.ReadExternalStorage)
        .then((value) {
      if (value == PermissionStatus.authorized) {
        try {
          Stream<FileSystemEntity> fileList =
              Directory(file).list(recursive: false, followLinks: false);

          // await for(FileSystemEntity s in fileList) { print(s); }
          List<Note> array = [];
          fileList.forEach((x) {

            if (x is File) {
              var res1 = ((x as File).readAsString()).then((value2) {
                Note note = Note.fromJsonResponse(value2);
                return note;
              }).catchError((error) {
                debugPrint('is not file content futurestring getNoteError: $x');
                return null;
              });
              var array2 = res1.then((value3) {
                array.add(value3);
                return array;
              });
            //?
            } else {
              debugPrint('is not file getNoteError: $x');
            }
          });


          // Add the file to the files array
          //Return the Future<List<Note>>
          return array;

        } catch (e) {
          debugPrint('getNoteError: $e');
          // If encountering an error, return 0
          return null;
        }
      } else {
        SimplePermissions.openSettings();
        return null;
      }
    });
  }
}

显然它不起作用,但即使尝试使用注释掉的部分等待循环也会引发错误。

在“getNotes”中,检查权限后我想获取目录中所有文件的数组,将它们解析为Note对象并返回结果数组。

我得到文件列表:

Stream<FileSystemEntity> fileList =
          Directory(file).list(recursive: false, followLinks: false);

对于流中的每一个,我想将文件解析为一个对象并将其附加到一个数组中以在最后返回。

       List<Note> array = [];
      fileList.forEach((x) {

        if (x is File) {
          var res1 = ((x as File).readAsString()).then((value2) {
            Note note = Note.fromJsonResponse(value2);
            return note;
          }).catchError((error) {
            debugPrint('is not file content futurestring getNoteError: $x');
            return null;
          });
          var array2 = res1.then((value3) {
            array.add(value3);
            return array;
          });
        //?
        } else {
          debugPrint('is not file getNoteError: $x');
        }
      });


      // Add the file to the files array
      //Return the Future<List<Note>>
      return array;

【问题讨论】:

  • 编辑了问题以使其更清晰。如果您有任何其他问题,请告诉我。
  • 好的,知道了。如果您需要所有元素并且不希望使用 .toList() 将它们一一转换,则可以将流转换为 Future;最后归还那个未来。谢谢。
  • 当然,欢迎您,如果您必须对 Stream 的元素执行一些 Future 操作,Stream#asyncMap 非常方便
  • 错误是什么?请在帖子中包含它。

标签: asynchronous dart flutter async-await future


【解决方案1】:

Stream.forEach() 返回一个Future。您的最后一个 return 语句在 for-each 调用之后立即运行,但应该 await 它。

await fileList.forEach((x) {
  ...

https://api.dartlang.org/stable/2.2.0/dart-async/Stream/forEach.html

【讨论】:

    猜你喜欢
    • 2018-09-18
    • 2020-09-02
    • 2020-10-02
    • 1970-01-01
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    • 2020-01-29
    • 2014-01-10
    相关资源
    最近更新 更多