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



当我在Android Studio中启动应用程序时,我必须将资产文件夹中的一个文件转换为file,以便将其作为RDF模型读取。问题是我的文件现在越来越大,应用程序通常会崩溃,或者文件下载时间太长。这个文件大约是170.384MB,所以它是一个相当大的文件,但我希望这个文件在我完成之前能增长到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();
}
}

谢谢你的帮助!

如何显示进度条

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

在doInBackground方法内循环时更新,如下所示

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服务器套接字,以便用户从应用程序连接客户端,然后简单地查询计算机上的文件并将适当的信息返回给用户。这提高了我的应用程序性能,并结束了应用程序无法接受的10分钟下载期。

最新更新