在 Android Studio 中下载文件需要很长时间
File taking a long time to download in Android Studio
当我在 Android Studio 中启动我的应用程序时,我必须将一个文件从我的资产文件夹转换为一个文件,以便将其作为 RDF 模型读取。问题是我的文件现在越来越大,应用程序通常会崩溃,或者文件下载时间太长。该文件大约有 170.384 MB,所以它是一个相当大的文件,但我预计在我完成之前该文件会增长到 1GB 左右。我在这里搜索了关于如何让文件下载更快的答案,但我没有看到任何我没有尝试过的新内容。例如,我启动了一个 AsyncTask,以便在与主 UI 线程不同的线程上执行 "download" 操作。这阻止了我的应用程序崩溃,但文件下载时间仍然太长,而且通常会超时。这是我在 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;
}
如您所见,我必须创建一个新的文件路径并创建一个新文件,创建一个 InputStream 以便从资产中读取文件,并将 InputStream 写入文件以便在 TDB 中加载 RDF 模型店铺。正是在这个过程中,我的应用程序开始在 AsyncTask 中 "time out"。
我遇到的另一个问题是在加载文件时更新我的进度条。我不确定如何获取 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 class 的完整代码。我想 post 代码的相关部分,但它们可能在我的代码的更广泛上下文中引起了问题:
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();
}
}
感谢您的帮助!
How to show progressbar
输入流的长度与文件大小相同(以字节为单位)。正如您知道文件的大小,只需乘以 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 应用程序上传大文件的类似问题,只需考虑使用后端服务器来存储数据。这是我最终做出的决定,因为将大文件直接下载到应用程序需要很长时间,因为移动设备的内存有限。从计算机 运行 服务器并连接 phone 上的客户端以在适当的时间检索相关信息更有意义。否则,您最终将拥有一个文件,该文件会耗尽移动设备上的存储空间,这将使您的最终用户的性能大大降低。我最终决定将 RDF 文件存储在计算机上,将文件上传到计算机上,运行 一个 Java 服务器套接字,以便用户从应用程序连接客户端,然后简单地查询计算机上的文件,并 return 向用户提供适当的信息。这提高了我的应用程序性能并结束了 10 分钟的下载时间,这对于应用程序来说是不可接受的。
当我在 Android Studio 中启动我的应用程序时,我必须将一个文件从我的资产文件夹转换为一个文件,以便将其作为 RDF 模型读取。问题是我的文件现在越来越大,应用程序通常会崩溃,或者文件下载时间太长。该文件大约有 170.384 MB,所以它是一个相当大的文件,但我预计在我完成之前该文件会增长到 1GB 左右。我在这里搜索了关于如何让文件下载更快的答案,但我没有看到任何我没有尝试过的新内容。例如,我启动了一个 AsyncTask,以便在与主 UI 线程不同的线程上执行 "download" 操作。这阻止了我的应用程序崩溃,但文件下载时间仍然太长,而且通常会超时。这是我在 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;
}
如您所见,我必须创建一个新的文件路径并创建一个新文件,创建一个 InputStream 以便从资产中读取文件,并将 InputStream 写入文件以便在 TDB 中加载 RDF 模型店铺。正是在这个过程中,我的应用程序开始在 AsyncTask 中 "time out"。
我遇到的另一个问题是在加载文件时更新我的进度条。我不确定如何获取 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 class 的完整代码。我想 post 代码的相关部分,但它们可能在我的代码的更广泛上下文中引起了问题:
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();
}
}
感谢您的帮助!
How to show progressbar
输入流的长度与文件大小相同(以字节为单位)。正如您知道文件的大小,只需乘以 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 应用程序上传大文件的类似问题,只需考虑使用后端服务器来存储数据。这是我最终做出的决定,因为将大文件直接下载到应用程序需要很长时间,因为移动设备的内存有限。从计算机 运行 服务器并连接 phone 上的客户端以在适当的时间检索相关信息更有意义。否则,您最终将拥有一个文件,该文件会耗尽移动设备上的存储空间,这将使您的最终用户的性能大大降低。我最终决定将 RDF 文件存储在计算机上,将文件上传到计算机上,运行 一个 Java 服务器套接字,以便用户从应用程序连接客户端,然后简单地查询计算机上的文件,并 return 向用户提供适当的信息。这提高了我的应用程序性能并结束了 10 分钟的下载时间,这对于应用程序来说是不可接受的。