【发布时间】: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为我真正实现同步。 -
据我所知,这些方法只是为了方便构造
FileInputStream和FileOutputStream对象(See ContextImpl)。因此,您依赖于处理文件锁定的操作系统。因此,我会谨慎并手动执行文件锁定。你可以看看FileChannel(可从FileInputStream和FileOutputStream访问)和FileLock,也许它们就足够了。
标签: java android caching synchronization android-webview