【问题标题】:Synchronization between Context.openFileInput and Context.openFileOutputContext.openFileInput 和 Context.openFileOutput 之间的同步
【发布时间】:2018-06-18 16:22:50
【问题描述】:

我有一个每天运行的 Android Service,它会进行一些数据同步。它每天下载一次文件并通过context.openFileOutput 将其缓存到磁盘:

String fileName = Uri.parse(url).getLastPathSegment();
try (FileOutputStream outputStream =
     context.openFileOutput(fileName, Context.MODE_PRIVATE)) {
   outputStream.write(bytes);
   // ...
} catch (IOException e) {
   // logging ...
}

这发生在背景线程上。 我还有一个包含WebView 的用户界面。 WebView 使用那些通过context.openFileInput 可用的缓存资源:

@Override
public WebResourceResponse shouldInterceptRequest(
    WebView view, WebResourceRequest request) {
  String url = request.getUrl().toString();
  if (shouldUseCache(url)) {
     try {
        return new WebResourceResponse(
             "video/webm",
             Charsets.UTF_8.name(),
             context.openFileInput(obtainFileName(url)));
     } catch (IOException e) {
       // If a cached resource fails to load, just let the WebView load it the normal way.
       // logging ...
     }
  }
  return super.shouldInterceptRequest(view, request);
}

这发生在独立于服务的另一个背景线程上。

我可以依靠Context 实现并确保文件读写是安全的,还是我必须自己处理同步? 例如。如果Service 当前正在将数据写入文件并且WebView 正在尝试访问它,我会遇到问题吗?如果是这样,我应该如何实现同步?

【问题讨论】:

  • 如果有任何修改,您可以使用 FileObserver 将内容重新加载到 WebView 中。
  • 如果您要自己处理同步,也可以使用 ReentrantLock。
  • @RahulKumar 感谢您的回复!问题是 shouldInterceptRequest 实际上是由 web 视图调用的,所以它会独立于文件观察者工作,所以我看不出它会有什么帮助。关于锁,你是说我 需要实现同步,即调用context.openFileInput的时候还没有同步?如果是这样,如果它们是两个不同的后台线程,我如何共享锁?一个在服务中,一个在 Web 视图中。这看起来很复杂,我还是希望Android为我真正实现同步。
  • 据我所知,这些方法只是为了方便构造FileInputStreamFileOutputStream 对象(See ContextImpl)。因此,您依赖于处理文件锁定的操作系统。因此,我会谨慎并手动执行文件锁定。你可以看看FileChannel(可从FileInputStreamFileOutputStream访问)和FileLock,也许它们就足够了。

标签: java android caching synchronization android-webview


【解决方案1】:

如果服务当前正在将数据写入文件并且 WebView 是 尝试访问它,我会遇到问题吗?

在这种情况下,您可以通过在文件名上附加一些内容并在下载完成后将其名称改回来将数据写入文件。例如

context.openFileOutput(fileName + ".downloading", Context.MODE_PRIVATE))

下载完成后将文件重命名为原始fileName。我相信您会检查shouldUseCache(url) 中的文件是否存在,因此它将继续正常工作。这将避免在您尝试读取文件时仍在下载文件的情况。

【讨论】:

  • 到目前为止,没有理由认为这些方法是由 Android 同步的,所以我认为我必须假设它们不是。我一直在寻找一种简单的方法来实现同步,你建议的是一个非常好的选择,出于某种原因,我没有想到......我肯定会走这条路。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-21
  • 2017-08-02
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 2021-10-16
  • 2017-05-14
相关资源
最近更新 更多