繁体   English   中英

在 Android Studio 中下载文件需要很长时间

[英]File taking a long time to download in Android Studio

当我在 Android Studio 中启动我的应用程序时,我必须将文件从我的资产文件夹转换为文件,以便将其作为 RDF 模型读取。 问题是我的文件现在越来越大,应用程序通常会崩溃,或者文件下载时间过长。 该文件大约为 170.384 MB,所以它是一个相当大的文件,但我希望这个文件在我完成之前会增长到 1GB 左右。 我在这里搜索了有关如何更快地下载文件的答案,但我没有看到任何我没有尝试过的新东西。 例如,我启动了一个 AsyncTask,以便在与主 UI 线程不同的线程上执行“下载”操作。 这阻止了我的应用程序崩溃,但文件仍然需要很长时间才能下载并且通常会超时。 这是我在 AsyncTask 中下载文件的代码示例:

 @Override
 public Model doInBackground(String... params){
        Model tdb = null;
        try {
            String filePath = context.getFilesDir() + File.separator + "my_turtle.ttl";
            File destinationFile = new File(filePath);
            FileOutputStream outputStream = new FileOutputStream(destinationFile);
            AssetManager assetManager = context.getAssets();
            InputStream inputStream = assetManager.open("sample_3.ttl");
            byte[] buffer = new byte[1024];
            int length = 0;
            int per = 0;
            while ((length = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, length);
                publishProgress(per);
                per++;
            }
            inputStream.close();
            outputStream.close();


            Dataset dataset = TDBFactory.createDataset();
            tdb = dataset.getNamedModel("my_dataset.ttl");
            ///Model m = FileManager.get().loadModel(FileManager.get().readWholeFileAsUTF8(inputStream));
            TDBLoader.loadModel(tdb, filePath, false);
            model = tdb;
            MainActivity.presenter.setModel(model);
        }catch(java.io.FileNotFoundException e){
            e.printStackTrace(System.out);
        }
        catch(java.io.IOException e){
            e.printStackTrace(System.out);
        }
        return tdb;
    }

如您所见,我必须创建一个新的 filePath 并创建一个新文件,创建一个 InputStream 以便从资产中读取文件,并将 InputStream 写入文件以便在 TDB 存储中加载 RDF 模型。 正是在这个过程中,我的应用程序开始在 AsyncTask 中“超时”。

我遇到的另一个问题是在加载文件时更新我的​​进度条。 我不知道如何获得 InputStream 的长度,我在我的代码中做这样的事情:

while ((length = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, length);
                publishProgress(per); //Publishing progress here...
                per++;
            }

发布进度应该触发 onProgressUpdate 方法():

@Override
public void onProgressUpdate(Integer... progress){
        progressBar.setProgress(progress[0]);
        pd.setProgress(progress[0]);
    }

但由于某种原因,我的 ProgressBar 和 ProgressDialog 在整个上传时间保持在 0%(即使我使用将上传的较小文件)。 我不确定为什么会这样。

下面是我的 AsyncTask 类的完整代码。 我想发布代码的相关部分,但它们可能是我的代码更广泛的上下文中导致问题的内容:

 public class DownloadModel extends AsyncTask<String, Integer, Model> {
    Context context;
    Model model = null;
    ProgressDialog pd;

    public DownloadModel(Context context){
        this.context = context;
        this.pd = new ProgressDialog(context);
    }

    @Override
    public Model doInBackground(String... params){
        Model tdb = null;
        try {
            String filePath = context.getFilesDir() + File.separator + "my_turtle.ttl";
            File destinationFile = new File(filePath);
            FileOutputStream outputStream = new FileOutputStream(destinationFile);
            AssetManager assetManager = context.getAssets();
            InputStream inputStream = assetManager.open("sample_3.ttl");
            byte[] buffer = new byte[10000000];
            int length = 0;
            int per = 0;
            while ((length = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, length);
                publishProgress(per);
                per++;
            }
            inputStream.close();
            outputStream.close();


            Dataset dataset = TDBFactory.createDataset();
            tdb = dataset.getNamedModel("my_dataset.ttl");
            ///Model m = FileManager.get().loadModel(FileManager.get().readWholeFileAsUTF8(inputStream));
            TDBLoader.loadModel(tdb, filePath, false);
            model = tdb;
            MainActivity.presenter.setModel(model);
        }catch(java.io.FileNotFoundException e){
            e.printStackTrace(System.out);
        }
        catch(java.io.IOException e){
            e.printStackTrace(System.out);
        }
        return tdb;
    }

    @Override
    public void onProgressUpdate(Integer... progress){
        progressBar.setProgress(progress[0]);
        pd.setProgress(progress[0]);
    }

    @Override
    public void onPreExecute(){
        pd.setMessage("Loading Knowledgebase...");
        pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        pd.setMax(100);
        pd.show();
    }

    @Override
    public void onPostExecute(Model i){
        progressBar.setVisibility(View.GONE);
        pd.dismiss();
    }
  }

感谢您的帮助!

如何显示进度条

输入流的长度与以字节为单位的文件大小相同。 正如您知道文件的大小一样,只需通过乘以 1024*1024 将其从 Mb 转换为字节,您就可以使用此硬编码值。

在 doInBackground 方法中更新 while 循环,如下所示

int size = 0;
        while ((length = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, length);
            size += length;
            publishProgress(size*100/your_file_size_in_bytes);
        }

如果您正在处理单个文件,则无法加速该过程。

但是,如果您有多个文件,则可以使用 ThreadPoolExecutor 并行运行多个线程。

我最终找到了一个非常不同的解决方案。 如果有人遇到类似为 Android Studio 应用上传大文件的问题,只需考虑使用后端服务器来存储数据。 这是我最终做出的决定,因为将大文件直接下载到应用程序中需要很长时间,因为移动设备的内存有限。 从计算机运行服务器并在电话上连接客户端以在适当的时间检索相关信息更有意义。 否则,您最终将拥有一个文件,它会占用移动设备上的存储空间,这将使您的最终用户的性能大大降低。 我最终决定将 RDF 文件存储在计算机上,将文件上传到计算机上,运行 Java Server Socket 以便用户从应用程序连接客户端,然后简单地查询计算机上的文件并返回适当的信息给用户。 这提高了我的应用程序性能并结束了应用程序无法接受的 10 分钟下载期。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM