我正在尝试在Dart(Flutter)中创建文件缓存,其中文件仅下载一次,然后缓存以备将来使用。 (是的,我知道已经有与此相关的软件包,但是我的需求更加具体。)

问题是,如果我在同一页面上有两个小部件试图显示相同的图像,则它们都在同一时间发出相同的请求,两次下载文件。

我试图将缓存变成一个单例,分发它自己的一个实例,但这似乎没有效果:

class FileCache {
  final _fileList = List<File>();
  static FileCache _instance;

  factory FileCache() {
    if (_instance == null) {
      _instance = FileCache._internal();
    }
    return _instance;
  }

  FileCache._internal();

  bool add(File file) {
    if (_fileList.contains(file)) {
      return false;
    }
    _fileList.add(file);
    return true;
  }

  void remove(File file) {
    _fileList.remove(file);
  }
}

我确实看到了另一个进行同步的包(here),但是看着Dart代码,我不知道它是如何执行同步访问的。

在Dart中,您如何为此目的强制串行访问特定的类或成员变量?

最佳答案

Flutter UI在单个隔离中运行。内存不是跨隔离共享的(因此得名),因此您不必担心并行操作(就像在多核系统上使用多个线程一样)。但是,您确实需要担心在从await执行产生时可以并发进行的并发操作。
这意味着您不需要特殊的原子基元。您可以在下载文件时设置标志,以避免再次下载。
您不会在任何地方使用Future,因此没有地方可以中断您的代码(如图所示)。但是,您也不会在实际下载文件的位置显示代码,并且大概在那里不同步。您可以执行以下操作:

final pendingDownloads = <String, Future<void>>{};
Future<void> downloadFile(String url) {
  if (pendingDownloads.containsKey(url)) {
    return pendingDownloads[url];
  }

  Future<void> downloadFileInternal() async {
    final request = await HttpClient().getUrl(...);
    ...
  }

  pendingDownloads[url] = downloadFileInternal();
  return pendingDownloads[url];
}

关于dart - 防止同时访问Dart中的相同数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55699545/

10-16 22:07