进度条在等待Future完成时未显示

时间:2014-01-12 01:01:19

标签: android asynchronous future

我正在编写一些代码来发现在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线程中的任何工作完成之前和之后设置了可见性,所以这里有什么问题?为什么不起作用?

2 个答案:

答案 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