开发者

Show result of long task after a ProgressDialog

I have an application which runs a long task and returns a value. While the task is running, a 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜