我有一个for循环,它调用一个函数来下载文件。 每次调用该函数时,文件的标题都显示在TextView中。 问题是文件被下载但UI冻结了,只有在文件下载完成后才更新UI,并且只显示最后一个文件的最后一个标题。
for(int i=0; i < Titles.size(); i++){
downloading.setText("Downloading: "+Titles.get(i));
if(!Utils.downloadFile(Mp3s.get(i))){
downloading.setText("ERROR Downloading: "+Titles.get(i));
}
}
我知道我必须使用Handler或Thread来解决这个问题。 但我不确定如何实施它。
答案 0 :(得分:1)
您可以尝试使用Activity.runOnUiThread()
- 例如:
// Move download logic to separate thread, to avoid freezing UI.
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i < Titles.size(); i++) {
// Those need to be final in order to be used inside
// Runnables below.
final String title = Titles.get(i);
// When in need to update UI, wrap it in Runnable and
// pass to runOnUiThread().
runOnUiThread(new Runnable() {
@Override
public void run() {
downloading.setText("Downloading: "+title);
}
});
if(!Utils.downloadFile(Mp3s.get(i))) {
runOnUiThread(new Runnable() {
@Override
public void run() {
downloading.setText("ERROR Downloading: "+title);
}
});
}
}
}).start();
那是非常冗长的(是的,Java!),而且在我看来,不太可读。
另一种解决方案是使用AsyncTask,它具有方便的onProgressUpdate()
方法,旨在为长时间运行的任务更新UI。它可能看起来像:
public class DownloadTask extends AsyncTask<URL, String, Void> {
// This method will be run off the UI thread, no need to
// create separate thread explicitely.
protected Long doInBackground(URL... titles) {
for(int i=0; i < titles.length; i++) {
publishProgress("Downloading " + titles[i]);
if(!Utils.downloadFile(Mp3s.get(i))) {
publishProgress("ERROR Downloading: " + titles[i]);
}
}
}
// This method will be called on the UI thread, so
// there's no need to call `runOnUiThread()` or use handlers.
protected void onProgressUpdate(String... progress) {
downloading.setText(progress[0]);
}
}
(请注意上面的代码是手写的未编译的,所以它可能是错误的,但它应该让你知道如何从这里开始。