Android: notifyDataSetChanged () не обновляет просмотр списка после изменения ориентации - PullRequest
6 голосов
/ 21 июня 2010

У меня есть полусложная проблема, и я надеюсь, что кто-то здесь сможет мне помочь.

В случае щелчка я создаю поток и запускаю длительную операцию, основанную на this метод.После завершения долгосрочной задачи она выполняет обратный вызов другого метода, который отправляет сообщение обработчику:

@Override
public void contentSearchModelChanged(Model_ContentSearch csm, ArrayList<Class_Reminder> newRemindersList) {
    remindersList = newRemindersList;
    mHandler.post(mUpdateDisplayRunnable);
}

, который вызывает Runnable:

// post this to the Handler when the background thread completes
private final Runnable mUpdateDisplayRunnable = new Runnable() {
  public void run() {
    updateDisplay();
  }
};

Наконец,Вот что делает мой метод updateDisplay ():

private void updateDisplay() {
    if (csModel.getState() != Model_ContentSearch.State.RUNNING) {
        if(remindersList != null && remindersList.size() > 0){
                r_adapter = new ReminderAdapater(Activity_ContentSearch.this, remindersList, thisListView);
                thisListView.setAdapter(r_adapter);
                r_adapter.notifyDataSetChanged();
        }
    }
}

Это прекрасно работает, когда я делаю это нормально.Однако, если я изменю ориентацию во время выполнения длительной операции, она не будет работать.Он действительно выполняет обратный вызов, и в нем есть элементы.Но когда доходит до этой строки:

r_adapter.notifyDataSetChanged();

Ничего не происходит.Странно то, что если я выполняю еще одну отправку и снова запускаю весь процесс (без изменения ориентации), он фактически обновляет представление дважды, один раз для предыдущей отправки и снова для следующей.Таким образом, представление обновляется один раз с результатами первой отправки, затем снова с результатами второй отправки через секунду.Таким образом, адаптер получил данные, он просто не обновляет представление.

Я знаю, что это как-то связано с изменением ориентации, но я не могу понять, почему.Кто-нибудь может помочь?Или кто-нибудь может предложить альтернативный метод обработки потоков с изменением ориентации?

Бара

Ответы [ 2 ]

6 голосов
/ 21 июня 2010

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

Это не легко исправить. Хотя есть библиотека, которая может вам помочь. Это называется DroidFu. Вот запись в блоге, которая (намного точнее, чем я) описывает основную причину того, что вы видите, и то, как библиотека DroidFu борется с этим: http://brainflush.wordpress.com/2009/11/16/introducing-droid-fu-for-android-betteractivity-betterservice-and-betterasynctask/

Редактировать: (Добавление кода для отслеживания активной активности)

В вашем классе приложения добавьте:

private Activity _activeActivity;
public void setActiveActivity(Activity activity) {
    _activeActivity = activity;
}
public Activity getActiveActivity() {
    return _activeActivity;
}

В своей деятельности добавьте:

@Override
public void onResume() {
    super.onResume();
    ((MyApplicationClassName)getApplication()).setActiveActivity(this);
}

Теперь вы можете получить активную активность, вызвав MyApplicationClassName.getActiveActivity ();

Это не так, как это делает DroidFu. DroidFu устанавливает активную активность в onCreate, но я не чувствую, что это очень надежно.

1 голос
/ 06 марта 2011

У меня была похожая проблема: у меня был трудоемкий поток sendEmptyMessage для обработчика, который в свою очередь вызывал notifyDataSetChanged в ListAdapter. Работало нормально, пока я не сменил ориентацию.

Я решил это, объявив второй обработчик в потоке пользовательского интерфейса и сделав первый обработчик sendEmptyMessage для этого обработчика, который в свою очередь вызвал notifyDataSetChanged в ListAdapter. И объявив ListAdapter как статический.

Я новичок, поэтому я не знаю, уродливое ли это решение, но оно сработало для меня ...

Из описания Jere.Jones я бы предположил, что это работает следующим образом: Длительный процесс sendEmptyMessage для дескриптора из старого Activity, который, в свою очередь, отправляет дескриптор вEmptyMessage в новый Activity.

...