Codenameone 将任意文件下载到Android和iOS缓存
我写了以下方法:Codenameone 将任意文件下载到Android和iOS缓存,codenameone,Codenameone,我写了以下方法: /** * Downloads an arbitrary file to the cache asynchronously, if the current * platform has a cache path, or to the app home; if the file was previously * downloaded and if it's still available on the cache, it calls the
/**
* Downloads an arbitrary file to the cache asynchronously, if the current
* platform has a cache path, or to the app home; if the file was previously
* downloaded and if it's still available on the cache, it calls the
* onSuccess callback immediatly.More info:
* https://www.codenameone.com/blog/cache-sorted-properties-preferences-listener.html
*
* @param url The URL to download.
* @param extension you can leave it empty or null, however iOS cannot play
* videos without extension (https://stackoverflow.com/q/49919858)
* @param onSuccess Callback invoked on successful completion (on EDT by
* callSerially).
* @param onFail Callback invoked on failure (on EDT by callSerially).
*/
public static void downloadFileToCache(String url, String extension, SuccessCallback<String> onSuccess, Runnable onFail) {
FileSystemStorage fs = FileSystemStorage.getInstance();
if (extension == null) {
extension = "";
}
if (extension.startsWith(".")) {
extension = extension.substring(1);
}
String name = "cache_" + HashUtilities.sha256hash(url);
if (!extension.isEmpty()) {
name += "." + extension;
}
String filePath;
if (fs.hasCachesDir()) {
// this is supported by Android, iPhone and Javascript
filePath = fs.getCachesDir() + fs.getFileSystemSeparator() + name;
} else {
// The current platform doesn't have a cache path (for example the Simulator)
String homePath = fs.getAppHomePath();
filePath = homePath + fs.getFileSystemSeparator() + name;
}
// Was the file previously downloaded?
if (fs.exists(filePath)) {
CN.callSerially(() -> onSuccess.onSucess(filePath));
} else {
Util.downloadUrlToFileSystemInBackground(url, filePath, (evt) -> {
if (fs.exists(filePath)) {
CN.callSerially(() -> onSuccess.onSucess(filePath));
} else {
CN.callSerially(onFail);
}
});
}
}
/**
*将任意文件异步下载到缓存(如果当前
*平台有缓存路径,或到应用程序主页;如果该文件以前已被删除
*已下载,如果缓存中仍有该文件,则调用
*onSuccess立即回调。详细信息:
* https://www.codenameone.com/blog/cache-sorted-properties-preferences-listener.html
*
*@param url要下载的url。
*@param extension您可以将其保留为空或null,但iOS无法播放
*无扩展的视频(https://stackoverflow.com/q/49919858)
*@param onSuccess回调在成功完成时调用(在EDT上由
*连续呼叫)。
*@param onFail回调在失败时调用(在EDT上由callSerially调用)。
*/
public static void downloadFileToCache(字符串url、字符串扩展名、SuccessCallback onSuccess、Runnable onFail){
FileSystemStorage fs=FileSystemStorage.getInstance();
if(扩展==null){
扩展名=”;
}
if(扩展名为startsWith(“.”){
扩展=扩展。子字符串(1);
}
String name=“cache_”+HashUtilities.sha256hash(url);
如果(!extension.isEmpty()){
名称+=“+”扩展名;
}
字符串文件路径;
if(fs.hasCachesDir()){
//Android、iPhone和Javascript都支持这一点
filePath=fs.getCachesDir()+fs.getFileSystemSeparator()+name;
}否则{
//当前平台没有缓存路径(例如模拟器)
字符串homePath=fs.getAppHomePath();
filePath=homePath+fs.getFileSystemSeparator()+name;
}
//文件以前下载过吗?
如果(fs.exists(filePath)){
CN.callSerially(()->onSuccess.onSucess(filePath));
}否则{
Util.downloadUrlToFileSystemInBackground(url,文件路径,(evt)->{
如果(fs.exists(filePath)){
CN.callSerially(()->onSuccess.onSucess(filePath));
}否则{
CN.callSerially(onFail);
}
});
}
}
它起作用了。它类似于类提供的一些方法,但有两个主要区别:第一个是类提供的方法仅用于将图像下载到缓存,而我希望下载任意文件;第二个是,我可以假设相同的url总是返回相同的文件,因此如果它仍然在缓存中,我就不需要再次下载它(而方法在调用时总是下载文件)
不过,我有一些疑问
callSerially
表示怀疑。以前我没有使用它,但我得到了奇怪的结果:我的回调进行UI操作,并且经常(但不总是)出现问题。我通过添加callSerially
解决了所有回调问题,因此callSerially
是解决方案。但是为什么?奇怪的事实是ConnectionRequest
实例的addResponseListener(callback)
在后台调用Util.downloadUrlToFileSystemInBackground
的ActionListener
,因此在EDT中已经调用了回调(根据)。可以肯定的是,我在回调中测试了CN.isEdt()
,没有添加callSerially
,它返回了true
,因此理论上callSerially
是不必要的,但实际上是这样的。我的推理有什么问题调用才有影响。它将结果延迟到下一个EDT循环,而不是在现有线程中继续