Android ProgressBar未按预期更新?

时间:2014-05-31 05:18:18

标签: android multithreading android-asynctask tablelayout android-progressbar

我使用TableLayout动态填充AsyncTask行,但未获得预期的ProgressBar行为。

我最初将ProgressBar的最大值设置为我正在处理的项目数的三倍,以容纳三个操作。这是我的代码:

onPreExecute:

        progress.setMax(items.size() * 3); // We need to create the rows and add listeners to them

异步类

public class TableLoader extends AsyncTask<Object, String, Boolean>{

    @Override
    protected Boolean doInBackground(Object... params) {

    for (int i = 0; i < items.size(); i++) {
            // doStuffToCreateRow
            rows.add(row);

        progress.publishProgress();
    }
}

然后我有:

@Override
protected void onPostExecute(Boolean result) {
    super.onPostExecute(result);

    if (!isCancelled()) {
        for (int i = 0; i < rows.size(); i++) {
            table.addView(rows.get(i));
            progress.incrementProgressBy(1);
        }

        table.requestLayout();  

        listener.onTaskCompleted();
    }
}

其中publishProgress只是:

protected void onProgressUpdate(String... values) {
  progress.incrementProgressBy(1);
}

最后,在我的onPostExecute method中,我回调了使用AsyncTask的活动,在主要活动中看起来像这样:

public void onTaskCompleted() { // TableRows have been generated
    TableLayout itemTable = (TableLayout) findViewById(R.id.itemTable);

    for (int i = 0; i < itemTable.getChildCount(); i++) {
        TableRow row = (TableRow) itemTable.getChildAt(i);
                    // Create and add a listener to that row's checkbox
                    // progress.incrementProgressBy(1);
    }
            progress.setVisibility(View.GONE);
}

由于某种原因,初始增量正常工作并导致progressBar在完成后生成1/3(生成TableRows)。然后,在UI线程阻塞然后progressBar消失的情况下会有2-5秒的暂停,我将设置为在onTaskCompleted(第三个和最后一个操作)中的for循环终止后发生。然后显示数据。

为什么我的progressBar没有按预期更新?

我看过这个问题,但发现人们通过&lt; 1使用除法或不使用UI线程。据我所知,我正在使用UI线程进行更新,每次增加1个/项目数* 3。

4 个答案:

答案 0 :(得分:0)

不要在progress.setMax()内设置doInBackground(),而是在onPreExecute()内进行设置。您不应该从工作者/后台线程修改UI线程(主线程),并且确实存在doInBackground()运行的位置。在UI线程上运行onPreExecute()onProgressUpdate()onPostExecute()

答案 1 :(得分:0)

为什么您没有使用线程来更新进度条。这种方法非常适合更新进度........但如果你想手动设置,那么首先设置进度条的最大值只需在onPreExecute中调用下面的方法,然后调用onPostExecute

 progressBar.setProgress(value);

当你从onPreExecute调用时,Value应该是最大值的一半,然后从onPostExecute调用%百分比......但是我建议你使用一个线程来更新正确的进度。

答案 2 :(得分:0)

不要在onPostExecute中使用publishProgress。只需调用incrementProgressBy。

答案 3 :(得分:0)

出于某种原因,初始增量正常工作并导致progressBar在完成后达到1/3满

这意味着Async部分正常工作,你的第三个是涉及doInBackground / ProgressUpdate的部分,也就是说,重要的东西是在UI线程之外完成的,只是表示进度更新。 UI线程正在休眠,并且正在等待更新请求。

然后,在UI线程阻塞然后progressBar消失的情况下会有2-5秒的暂停,我已经设置为在onTaskCompleted中的for循环之后发生(第三次和最后一次操作) )终止。然后显示数据。

其他两个操作发生在UI线程中。 onPostExecutedonTaskCompleted中的 for 都在UI线程上运行并且是紧密循环。 您的循环中阻止了UI线程。因此,当你进入那些紧密的循环时,无论你与任何UI组件混合了多少次:setprogress,settext等.... 它将不会更新,直到for循环结束,你的例程完成,系统再次控制UI线程。

你可以做的是,因为看起来有很多行,要以块的形式添加它们然后更新进度。这会给一些空气。看看以下原型

 Handler handler=new Handler();

 interface AddRowListener {
      public void onRowsAdded();
 }

 private void addRowChunk(final int startRow, final int totalRows, final AddRowListener listener) {

          for (int i=startRow; i<startRow+CHUNK_SIZE; i++) {

               if (i>=totalRows) {
                    // we have finished! Just call the listener
                    listener.onRowsAdded();
                    return; 
               }
               addView....
          }

          // After adding some rows, we end here, and schedule a call to this function again
          // to continue. The 25ms delay is optional, but it will give some air to Android for sure

          handler.postDelayed(new Runnable() {
                addRowChunk(startRow+CHUNK_SIZE, totalRows, listener);
          }, 25);
 }

 private void addRows(AddRowListener listener) {

      TableLayout itemTable = (TableLayout) findViewById(R.id.itemTable);

      // we start the process, it will create row chunks and call the listener when done
      addRowChunk (0, itemTable.getChildCount(), listener); 
 }

所以要添加你现在可以做的行:

 addRows (new AddRowListener() {
       public void onRowsAdded() {

           // the rows have been added.

       }
 });

顺便问一下,你的行大小是多少?它必须是巨大的!

PD_您必须选择CHUNK_SIZE。只需尝试使用值,直到UI变得活泼。我说40-50是可以的,但这只是一个疯狂的猜测,取决于手机硬件。