第二次加载时,进度条失败

时间:2012-03-27 03:11:22

标签: java android multithreading exception-handling android-progressbar

我有一个简单的函数,可以在获取数据时显示加载微调器(通常需要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)

如果有人能告诉我或向我解释导致错误的原因,我将不胜感激

2 个答案:

答案 0 :(得分:2)

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

    runOnUiThread(new Runnable() {

        @Override
        public void run() {
            progressBar.dismiss();
        }
    });

答案 1 :(得分:1)

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

修改
This official link将帮助您掌握AsyncTask。要记住的是doInBackground()方法在单独的线程中运行,您应该在其中放置数据加载方法,即fetch_data()。一旦方法完成执行,将调用onPostExecute(),它将在UI线程上运行,您可以在其中关闭对话框。您可以在onPreExecute()方法中启动对话框 虽然在此上下文中您不需要onProgressUpdate()方法,但只需FYI,它用于在使用publishProgress()调用(如果您将来使用AsyncTask)加载仍在工作时更新UI线程中的Views。

PS:只有doInBackground()方法在单独的线程中运行,其他每个方法都在UI线程中运行。

,关于不在UI之外的任何其他线程中访问View的规则仍然适用。