Вопрос по android, listview, multithreading, android-asynctask – Заполнение списка в отдельной теме

2

В упражнении я загружаю строки списка, что занимает много времени, поэтому я помещаю эту задачу в отдельный поток, чтобы можно было отображать progressDialog.

Я делаю следующее

<code>private void doMyStuff() {
    listItems.clear();
    progressDialog.show();

    new Thread(new Runnable() {
        @Override
        public void run() {                
            for () {
                listItems.add(something to add);
            }
        handler.sendEmptyMessage(0);
        progressDialog.dismiss();
        }
    }).start();
}

private Handler handler = new Handler() {
    public void handleMessage(android.os.Message msg) {
        if (msg.what == 0) {
            adapter.notifyDataSetChanged();
        }
    };
};
</code>

У меня иногда есть ошибка, которая вызывает исключение IllegalStateException. Прежде всего, я был удивлен, потому что программирование потока, как это я обычно делаю в стандартных программах Java.

Ошибка появляется только & quot; иногда & quot; и он не появляется при пошаговой отладке.

Это привело меня к поиску в Интернете, и я нашел в SO несколько вопросов, связанных с этим, и я должен признать, что вещи не ясны для меня.

Поскольку я вызываю notifyDataSetChanged () только после завершения потока, почему он иногда вызывает исключение.

Может ли кто-нибудь подтвердить мне, что этот способ неправильный, и что я ДОЛЖЕН использовать асинхронную задачу и, возможно, объяснить мне, почему ???

Мне нужно, чтобы отображался progressDialog, может кто-нибудь дать мне простой пример AsyncTask, заполняющего представление списка И отображающий progressDialog заполняющего прогресса.

Спасибо

UPDATE

Jtanveer дал мне ответ на асинктивный вопрос. Теперь другие отметили, что увольнение не в обработчике, что я исправляю.

Согласно статье, опубликованной jtanveer на тему «Безболезненная резьба» они говорят, что

Android предлагает несколько способов доступа к потоку пользовательского интерфейса из других потоков, одним из которых является HANDLER.

Кто-то знает, почему помещение уволенного в обработчик не решило мою проблему? для меня listItem.add не имеет ничего общего с пользовательским интерфейсом? Я не прав в этом вопросе?

Для меня в моем коде единственный интерфейс это адаптер и progressdialog? Любые комментарии или объяснения приветствуются.

FINAL ANSWER

stjom дал рабочий ответ для моего конкретного кода. Запуск runOnUiThread в обработчике. Это работает, но я удивлен, потому что я думал, что обработчик был запущен в потоке пользовательского интерфейса ...

Спасибо всем за все ваши ответы.

Оба ответа у вас сейчас правильные. Вам не нужно использоватьAsyncTaskхотя это делает такие операции чистыми. То, что вы ДОЛЖНЫ сделать, - это все операции пользовательского интерфейса в потоке пользовательского интерфейса / основного потока, и это включает в себя закрытие диалогового окна прогресса. Вы можете использоватьAsyncTask пример ниже или просто добавьprogressDialog.dismiss() в вашHandler Перезвоните. Devunwired
Я считаю, что есть много примеров. Попробуйте поискать в Интернете что-то вроде "android progressdialog asynctask example". anon
+1 вам обоим за указание на эту ошибку. К сожалению, это не решило мою проблему, но я не понимаю, почему этот обработчик находится в потоке пользовательского интерфейса! HpTerm
Я обновил свой вопрос. почему ваши ответы не работают? HpTerm

Ваш Ответ

3   ответа
3

определить внутренний класс, как показано ниже:

private class LoadListTask extends AsyncTask<String, Void, Integer> {
    protected void onPreExecute() {
        progressDialog.show();
    }

    protected Integer doInBackground(String... params) {
        for () {
            listItems.add(something to add);
        }
        return 0;
    }

    protected void onPostExecute(Integer result) {
        progressDialog.dismiss();
        if (result == 0) {
           adapter.notifyDataSetChanged();
        }
    }
}

если вам нужно, вы можете обратиться к этомустатья.

Вы пытаетесь обновить пользовательский интерфейс из отдельного потока, что строго запрещено. Обновление пользовательского интерфейса должно быть сделано из потока пользовательского интерфейса. Возможно, именно поэтому вы получаете исключение.
Я не уверен, что вы можете добавлять элементы в коллекциюlistItems связан с адаптером в фоновом потоке. Иногда это может вызвать исключение. Поэтому я обычно создаю другой список (коллекцию), добавляю туда элементы. Затем в UI-потоке я добавляю коллекцию к адаптеру (adapter.addAll (newList); adapter.notifyDataSetChanged ();).
как я уже сказал, я исправил свой код и произвел увольнение в «обработчике» вот почему теперь я не понимаю, почему я все еще получаю ошибку, в то время как ваш код работает нормально HpTerm
Спасибо, что нашли время, чтобы ответить на вопрос. Это работает нормально и исправьте мою ошибку. Однако я не понимаю, почему ответы других не работают, так как помещение отклоненного в обработчик должно исправить это. HpTerm
2

Вам не нужно использовать AsyncTask, это просто удобство.

Что касается того, почему ваша текущая реализация иногда не работает - Вы должны закрыть свой диалог прогресса из потока пользовательского интерфейса, так что он должен идти в вашем обработчике, а не в фоновом потоке.

+1 за указание на ошибку. К сожалению, это не решило мою проблему, но я не понимаю, почему, потому что, как вы это заявляете, и, насколько я понимаю, это просто для «удобства». и поскольку обработчик находится в потоке пользовательского интерфейса, он все еще неясен для меня. HpTerm
2

всякий раз, когда вы звонитеadapter.notifyDataSetChanged(); он определяет любые изменения в вашемlistItems объект. если какое-либо изменение будет найдено, оно обновит пользовательский интерфейс соответственно, что, я думаю, вызывает вашу проблему. ты можешь позвонить

runOnUiThread(new Runnable() {
    public void run() {
        adapter.notifyDataSetChanged();
    }  
});

внутри вашего обработчика.

+1 это работает !!! Но вы указали что-то непонятное для меня. Почему обработчик не выполняется в потоке пользовательского интерфейса ??? Я думал, что обработчик был запущен в потоке пользовательского интерфейса. HpTerm

Похожие вопросы