ProgressDialog
shows the progress. After the task is done I want to show the result in a TextView
. I run the task in a FutureTask.
My problem is that if I try to get the result, the .get()
method of FutureTask blocks the UI Thread and I don't see the ProgressDialog
(the TextView
displays the result propertly).
My code for the task (pool is ExecutorService):
final FutureTask<String> future = new FutureTask<String>(new Callable<String>() {
@Override
public String call() {
return myLongTask();
}
});
pool.execute(future);
And afterwards I call updateProgressBar()
in a Runnable
which updates the ProgressDialog
with a Handler
:
Runnable pb = new Runnable() {
p开发者_C百科ublic void run() {
myUpdateProgressBar();
}
};
pool.execute(pb);
Now I'm getting the result, which blocks the UI Thread preventing the ProgressDialog
to show up:
String result = future.get()
If I try to put the result inside the updateProgressBar() method (by passing the future as a parameter) after the ProgressDialog dismisses, an Exception is thrown:
Only the original thread that created a view hierarchy can touch its views.
Any ideas how to solve this problem? (I've heard about AsyncTasks but I can't figure out how to use them propertly.)
You are correct that you need either an AsyncTask
or a Thread
/Handler
combination in order to not block the UI.
Neither approach is that tricky, and there are some good guides around that lay out how to do them. Here are some links that I'd recommend.
- AsyncTask
- Painless threading
- Threading
- Designing for responsiveness
- Thread documentation
- Handler documentation
Yes, I had similiar problem when implementing ExecutorService, the following code block the UI thread and need to be run on a separated thread:
String result = future.get()
Just create a class extending AsyncTask to handle the future.get()
method like the following code example:
private class FutureTask extends AsyncTask<Future<String>, Void, String>{
@Override
protected PhotoToView doInBackground(Future<String>... params) {
Future<String> f = params[0];
try {
return f.get(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String futureResult) {
super.onPostExecute(futureResult);
// this method is run on UI thread
// do something with the result
// or simply hide the progress bar
// if you had previously shown one.
}
}
And run the future thread with:
FutureTask ft = new FutureTask();
ft.execute(future);
Hope this helps.
精彩评论