我正在编写一些代码来发现在Android中处理异步性的不同方法,而且我已经完成了AsyncTask,现在我在过去曾经有过一些运气,但这次它让我烦恼了一下。 ..
代码本身工作正常,除了(旋转)进度条仅在下载操作完成后显示的事实...尽管我告诉代码在之前显示它...
这是代码:
public void startDownload(final String url) {
bar.setVisibility(View.VISIBLE); // progress bar should appear here
ExecutorService pool = Executors.newCachedThreadPool();
Gson gson = new Gson();
Future<String> promise = pool.submit(new Callable<String>() {
@Override
public String call() throws Exception {
String response = "";
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while((s = buffer.readLine()) != null) response += s;
} catch (IOException ioe) {
ioe.printStackTrace();
}
return response;
}
});
while(promise.isDone() == false) {
// wait
}
bar.setVisibility(View.GONE); // and disappear here
try {
GitHubStatus status = gson.fromJson(promise.get(), GitHubStatus.class);
statusText.setText(status.getStatus());
bodyText.setText(status.getBody());
dateText.setText(status.getCreationDate());
} catch (ExecutionException ee) {
ee.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
// instead it briefly appears here, and then disappears again
}
对于那些不知道的人;期货执行自己,因此你不需要调用“运行”或“启动”方法来启动它
我试图在等待它完成的循环中放置一个Log.v("DEBUG: ", "Loading...");
,它确实打印好消息,很多次就是
我试过没有循环,这也不起作用,我甚至试过ProgressDialog
也不起作用......
据我所知,在UI线程繁忙时我无法更新UI线程,但我只在UI线程中的任何工作完成之前和之后设置了可见性,所以这里有什么问题?为什么不起作用?
答案 0 :(得分:0)
请尝试以下操作:
public void startDownload(final String url) {
bar.setVisibility(View.VISIBLE); // progress bar should appear here
ExecutorService pool = Executors.newCachedThreadPool();
Gson gson = new Gson();
Future<String> promise = pool.submit(new Callable<String>() {
@Override
public String call() throws Exception {
String response = "";
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while((s = buffer.readLine()) != null) response += s;
} catch (IOException ioe) {
ioe.printStackTrace();
}
runOnUiThread(new Runnable()
{
public void run()
{
bar.setVisibility(View.GONE); // and disappear here
try {
GitHubStatus status = gson.fromJson(promise.get(), GitHubStatus.class);
statusText.setText(status.getStatus());
bodyText.setText(status.getBody());
dateText.setText(status.getCreationDate());
} catch (ExecutionException ee) {
ee.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
});
return response;
}
});
}
因为
while(promise.isDone() == false) {
// wait
}
你阻止了UIThread。
答案 1 :(得分:0)
FutureTask
可用于运行异步任务。但是,它的get()
方法和isDone()
方法在被调用时会阻塞。
因此,当您尝试在刚刚被ProgressBar
阻止的UI线程上显示FutureTask
时,直到完成FutureTask
后,它才会显示。
就您而言,您可以在发起ProgressBar
调用之前先启动FutureTask
,但这是正确的,但是一旦FutureTask
开始,ProgressBar
的运行就会被阻止。
要解决此问题,您可以在FutureTask
内运行AsyncTask
:
onPreExecute()
ProgressBar`的AsyncTask to show the
方法。onProgressUpdate()
的{{1}}方法来更新AsyncTask
上的进度。ProgressBar
的{{1}}方法隐藏onPostExecute()
;在最坏的情况下,您可以在AsyncTask
的{{1}} / ProgressBar
内部调用runOnUiThread()
,以隐藏FutureTask
。