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总是返回相同的文件,因此如果它仍然在缓存中,我就不需要再次下载它(而方法在调用时总是下载文件)

不过,我有一些疑问

  • 我的第一个问题是关于缓存的工作原理:目前我使用这种方法下载图像和视频以缓存(在聊天应用程序中),假设我不需要关心文件何时不再需要,因为操作系统会自动删除它们。是这样吗?是否有可能操作系统在我使用文件时删除文件(例如,在将文件存储到缓存后立即删除),或者Android和iOS仅删除较旧的文件

  • 我编写这个方法来存储任意文件。我们可以存储在缓存中的文件大小是否有合理的MB限制

  • 最后,我对我在方法中使用的
    callSerially
    表示怀疑。以前我没有使用它,但我得到了奇怪的结果:我的回调进行UI操作,并且经常(但不总是)出现问题。我通过添加
    callSerially
    解决了所有回调问题,因此
    callSerially
    是解决方案。但是为什么?奇怪的事实是
    ConnectionRequest
    实例的
    addResponseListener(callback)
    在后台调用
    Util.downloadUrlToFileSystemInBackground
    ActionListener
    ,因此在EDT中已经调用了回调(根据)。可以肯定的是,我在回调中测试了
    CN.isEdt()
    ,没有添加
    callSerially
    ,它返回了
    true
    ,因此理论上
    callSerially
    是不必要的,但实际上是这样的。我的推理有什么问题

  • 谢谢你的解释

  • 据我所知,缓存目录只是一个允许操作系统在需要空间时删除的目录。我不认为它会删除一个活动的前台应用程序,但这可能会有所不同

  • 除了存储之外,没有其他限制。但是你仍然需要考虑OS不会为你清理那个目录。它只会在存储空间非常低时进行刷新,即使如此,也不总是这样。因此,您仍然需要负责任地存储数据

  • 我认为只有第一个
    调用才有影响。它将结果延迟到下一个EDT循环,而不是在现有线程中继续