0

案例:我在活动中有一个按钮和列表视图。单击按钮时,我添加了一个单击侦听器,它启动了一个新线程,我在其中更新进度条。工作完成后,即进度条完成 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.

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

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

但是,这不起作用。它根本不显示进度条。

4

3 回答 3

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

于 2013-06-16T07:50:40.227 回答
1

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

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

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

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

      }
   }); 

我建议你使用 asynctask

为此,您使用 use asynctask。onPreExecute(), onPostExecute() 在 ui 线程上调用,您可以使用它们来更新 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(). 
于 2013-06-16T07:53:07.033 回答
0

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

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

于 2013-06-16T07:43:02.237 回答