1

我有一个简单的函数,显示在获取数据时加载微调器(通常需要 7 秒左右)

private void load_data(View v)
{
    task_complete = false;
    progressBar = new ProgressDialog(v.getContext());
    progressBar.setCancelable(false);
    progressBar.setMessage("Fetching data ...");
    progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    progressBar.show();

    try
    {
        Log.v("thread", "Starting thread");
        new Thread(new Runnable()
        {
            public void run()
            {
                while(!task_complete)
                {
                    fetch_data();
                    try
                    {
                        Thread.sleep(1000);
                    }
                    catch(InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
                progressBar.dismiss();
            }
        }).start();
        Log.v("thread", "Thread finished successfully");
    }
    catch(Exception e)
    {
        Log.v("thread", "fail "+e.toString());
    }
}

我遇到的问题是 onClick 通过调用该函数

load.setOnClickListener(new View.OnClickListener()
{
    public void onClick(View v)
    {
        load_data(v);
        show_data(v); // shows the data on a spinner
    }
});

当我第二次按下加载按钮时,我得到一个错误。我的日志确实显示

Starting thread
Thread finished successfully

但不知何故,该应用程序因错误而死

03-27 02:48:39.282: E/AndroidRuntime(956): Uncaught handler: thread Thread-9 exiting due to uncaught exception
03-27 02:48:39.293: E/AndroidRuntime(956): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
03-27 02:48:39.293: E/AndroidRuntime(956):  at android.view.ViewRoot.checkThread(ViewRoot.java:2683)

如果有人可以向我展示或向我解释导致错误的原因,我将不胜感激

4

2 回答 2

2

问题是你的progressBar.dismiss(); 在另一个线程中执行,使其在 UI 线程中运行,请执行以下操作:

    runOnUiThread(new Runnable() {

        @Override
        public void run() {
            progressBar.dismiss();
        }
    });
于 2012-03-27T04:46:51.947 回答
1

ProgressDialog是一个视图,您只能在 UI 线程(或主线程)中访问它。使用AsyncTask而不是线程。

编辑
这个官方链接将帮助您掌握 AsyncTask 的窍门。要记住的是 doInBackground() 方法在单独的线程中运行,您应该在其中放置数据加载方法,即 fetch_data()。一旦方法完成执行,onPostExecute() 将被调用,它将在 UI 线程上运行,您可以在其中关闭对话框。您可以在 onPreExecute() 方法中启动对话框。
尽管在这种情况下您不需要 onProgressUpdate() 方法,但仅供参考,它用于在加载仍在使用 publishProgress() 调用时更新 UI 线程中的视图(以防您将来使用 AsyncTask)。

PS:只有 doInBackground() 方法在单独的线程中运行,其他所有方法都在 UI 线程中运行。除了 UI 线程之外,关于不在任何其他线程中访问视图的规则在这里仍然适用。

于 2012-03-27T03:15:17.847 回答