Индикатор не работает при второй загрузке - PullRequest
1 голос
/ 27 марта 2012

У меня есть простая функция, которая показывает загрузку счетчика при получении данных (обычно это занимает около 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 ]

2 голосов
/ 27 марта 2012

Проблема в том, что ваш progressBar.dismiss (); выполняется в другом потоке, чтобы запустить его в потоке пользовательского интерфейса, выполните следующие действия:

    runOnUiThread(new Runnable() {

        @Override
        public void run() {
            progressBar.dismiss();
        }
    });
1 голос
/ 27 марта 2012

ProgressDialog является представлением, и вы можете получить к нему доступ только в потоке пользовательского интерфейса (или в основном потоке).Используйте AsyncTask вместо потоков.

EDIT
Эта официальная ссылка поможет вам освоить AsyncTask.Следует помнить, что метод doInBackground () запускается в отдельном потоке, в который вы должны поместить метод загрузки данных, например fetch_data ().Как только метод завершит выполнение, будет вызвана onPostExecute (), которая будет выполняться в потоке пользовательского интерфейса, где вы можете закрыть диалоговое окно.Вы можете запустить диалог в методе onPreExecute ().
Хотя в этом контексте вам не нужен метод onProgressUpdate (), а только FYI, он используется для обновления представлений в потоке пользовательского интерфейса, пока загрузка все еще работает с использованиемВызов publishProgress () (если вы будете использовать AsyncTask в будущем).

PS: Только метод doInBackground () запускается в отдельном потоке, все остальные методы выполняются в потоке пользовательского интерфейса.Правило о запрете доступа к представлению в любом другом потоке, кроме пользовательского интерфейса, все еще применяется здесь.

...