完成进度条后如何更新视图?

时间:2013-06-16 07:36:57

标签: android android-listview progress-bar

CASE:我在活动中有一个按钮和列表视图。单击按钮后,我添加了一个单击侦听器,它启动一个新线程,我在其中更新进度条。作业完成后,即进度条100%完成,我想更新列表视图。

final OnClickListener mStartScan = new OnClickListener() {

    @Override
    public void onClick(View v) {

        // prepare for a progress bar dialog
        progressBar = new ProgressDialog(v.getContext());
        progressBar.setCancelable(false);
        progressBar.setMessage(getString(R.string.text_scanning_inbox));
        progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressBar.setProgress(0);
        progressBar.setMax(totalSms);
        progressBar.show();

        progressBarStatus = 0;

        Thread progressThread = new Thread(new Runnable() {
            public void run() {
                while (progressBarStatus < totalSms) {

                    // process some tasks
                    progressBarStatus = someStuff();

                    // Update the progress bar
                    progressBarHandler.post(new Runnable() {
                        public void run() {
                            progressBar.setProgress(progressBarStatus);
                        }
                    });
                }

                if (progressBarStatus >= done) {

                    // sleep 1 seconds, so that you can see the 100%
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    // close the progress bar dialog
                    progressBar.dismiss();

                    // this method updates the list
                    populateList();
                }
            }
        });
        progressThread.start();

//          try {
//              progressThread.join();
//          } catch (InterruptedException e) {
//              // TODO Auto-generated catch block
//              e.printStackTrace();
//          } finally {
//              populateList();
//          }           
        }
};

问题:当我在完成任务并解除进度条后更新列表视图时,我收到一个异常,说明视图只能从创建它的线程更新。

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

我做了什么:我试图等待正在运行进度条的线程完成,然后从主线程更新listview。

try {
    progressThread.join();
} catch (InterruptedException e) {
    e.printStackTrace();
} finally {
    populateList();
}

然而,这不起作用。它根本不显示进度条。

3 个答案:

答案 0 :(得分:1)

我用过这个:

private ProgressDialog progressBar;

class MyTask extends AsyncTask<String, Void, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        progressBar = new ProgressDialog(getApplicationContext());
        progressBar.setMessage("please, waiting ...");
        progressBar.setCancelable(false);
        progressBar.show();

    }

    @Override
    protected String doInBackground(String... params) {

        try {
            // get info and set them in my model ...

        } catch (Exception e) {
            e.printStackTrace();
        }

        return params[0];
    }

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

        if (null != progressBar && progressBar.isShowing()) {
            progressBar.dismiss();
        }

        // do work in UI and set info adapter and refresh list ...
        populateList();
                    myListView.invalidateViews();
    }
}

了解更多信息: http://developer.android.com/reference/android/widget/ArrayAdapter.html#notifyDataSetChanged%28%29

答案 1 :(得分:1)

只有创建视图层次结构的原始线程才能触及其视图。

这里原始线程指的是ui线程。您正试图在线程内更新ui,这是不可能的。

您无法从后台线程更新ui。您可以使用runOnUiThread。

 runOnUiThread(new Runnable() //run on ui threa
  {
      public void run() 
      { 

      }
   }); 

我建议你使用asynctask

为此目的使用asynctask。在ui线程上调用onPreExecute(),onPostExecute(),你可以使用它来更新ui。您可以在doInbackground()

中进行背景计算

http://developer.android.com/reference/android/os/AsyncTask.html

检查标题“4个步骤”下的主题。

    class TheTask extends AsyncTask<Void,Void,Void>
    {

@Override
protected Void doInBackground(Void... params) {
    // TODO Auto-generated method stub
            // background computation and publish progress      
    return null;
}
    @Override
protected void onProgressUpdate(Void... values) {
    // TODO Auto-generated method stub
    super.onProgressUpdate(values);
           // update progress bar
}

@Override
protected void onPostExecute(Void result) {
    // TODO Auto-generated method stub
    super.onPostExecute(result);
            // cancel the progress bar
}

@Override
protected void onPreExecute() {
    // TODO Auto-generated method stub
    super.onPreExecute();
             //display progress bar    
}

}

在ui线程上加载asynctask

     new TheTask().execute(). 

答案 2 :(得分:0)

您收到的错误是因为您尝试更改辅助线程上的UI组件。您应该阅读this以获取有关如何在Android上使用线程的更多信息。

您可以使用Activity方法runOnUIThread()来调用populateList()方法或在UI(主)线程上进行更新的任何方法。如果您阅读上述文档,您会发现更多相关信息。