我确实有一个线程问题:
在我的一个活动中有一些网络操作(下载)要做。我为此写了一个线程,让它在UI线程的后台发生。但我做错了在某些方面,我不知道如何解决这个问题。我的代码是:
private void startDownload(){
progressBar.setVisibility(View.VISIBLE);
Downloader loader = new Downloader();
loader.start();
try {
loader.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
现在的问题是,进度条出现时,加载程序几乎完成。在我启动加载程序之前它不会显示出来。我认为这是因为我加入()加载器与我的UI线程,但我不知道如何规避这一点。我必须等待loader完成,因为下面的代码将处理从loader下载的文件。
我有一个想法:我可以使用像 这样的循环while(loader.isAlive()){
//doSomething
}
但我不确定这是否能解决我的问题。
编辑:好吧,我会用AsyncTask代替我的线程。这似乎是有道理的,因为在程序的进一步发展中,我需要UI中的数据。
但是有人可以向我解释为什么我的进度条没有显示,虽然我设置可见性为TRUE开始加载程序线程之前?谢谢你!
您需要在后台线程执行下载操作,并从UI线程更新UI。
为此,您可以使用AsyncTask:
:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
// TODO do actual download
// publish your download progress
publishProgress(count);
return null; // TODO insert your result
}
protected void onProgressUpdate(Integer... progress) {
// TODO set progress to progressbar
// update UI
}
protected void onPostExecute(Long result) {
// called when download is complete
// update UI
}
}
开始下载:
private void startDownload() {
progressBar.setVisibility(View.VISIBLE);
asyncTask = new DownloadFilesTask();
asyncTask.execute(<urls for download>);
}
使用异步任务
class MyTask extends AsyncTask...{
onPreExecute(){
showProgress();
}
doInbackground(){
//this by itself is a thread so you may need to change the Downloader code
//it should be normal class, not thread.
Downloader loader = new Downloader();
loader.doSomeWork();
//loader.start();
}
onPostExecute(){
//you should NOT hide the progress at the end of Downloader()
hideProgress();
}
这里是AsyncTask
Join()是一个阻塞调用,在线程被阻塞之前,您的进度条没有时间重新绘制。最好的方法是使用AsyncTask如上所述,但如果你想自己做,不要阻塞主线程。使用Handler或任何其他方法将您的更新发布到UI线程