6

Mam pół-skomplikowany problem i mam nadzieję, że ktoś tutaj będzie w stanie mi pomóc.Android: notifyDataSetChanged() nie aktualizuje listview po zmianie orientacji

W przypadku zdarzenia kliknięcia utworzę wątek i rozpocznę długotrwałą operację opartą na metodzie this. Po długo działa zadanie zostanie zakończone, to robi zwrotnego innego sposobu, który dokłada stanowisko do obsługi:

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

który wzywa do Runnable:

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

A oto co mój Metoda updateDisplay() wykonuje:

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(); 
     } 
    } 
} 

Działa to pięknie, gdy robię to normalnie. Jeśli jednak zmienię orientację, gdy działa długotrwała operacja, nie działa. Poprawia to wywołanie zwrotne, a parametr przypomnienia ma elementy w nim zawarte. Ale kiedy dojdzie do tej linii:

r_adapter.notifyDataSetChanged(); 

Nic się nie dzieje. Dziwne jest to, że jeśli wykonam kolejny proces i ponownie uruchomię cały proces (bez zmiany orientacji), to faktycznie aktualizuje on widok dwukrotnie, raz dla poprzedniego przesyłania i znowu dla następnego. Tak więc widok aktualizuje się raz z wynikami pierwszego zgłoszenia, a następnie ponownie z wynikami drugiego zgłoszenia sekundę później. Tak więc adapter DID pobiera dane, po prostu nie odświeża widoku.

Wiem, że to ma coś wspólnego ze zmianą orientacji, ale nie mogę dla mnie zrozumieć dlaczego. Czy ktoś może pomóc? Czy ktoś może zaproponować alternatywną metodę obsługi wątków ze zmianami orientacji?

Bara

Odpowiedz

6

Problemem jest to, że po zmianie orientacji nowa aktywność przędzie się od początku (onCreate). Twój długotrwały proces ma uchwyt do starej (już niewidocznej) aktywności. Poprawnie aktualizujesz stare działanie, ale ponieważ nie jest ono już wyświetlane na ekranie, nie widzisz go.

Nie jest to łatwy problem do rozwiązania. Istnieje jednak biblioteka, która może ci pomóc. Nazywa się DroidFu. Oto blogu, że (o wiele dokładniej niż I) opisuje podstawową przyczyną tego, co widzisz i jak biblioteka DroidFu zwalcza go: http://brainflush.wordpress.com/2009/11/16/introducing-droid-fu-for-android-betteractivity-betterservice-and-betterasynctask/

Edycja: (Dodanie kodu do śledzenia aktywną działalność)

W klasa aplikacja dodać to:

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

W swojej działalności, dodać to:

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

teraz można uzyskać aktywnego aktywno ty przez wywołanie MyApplicationClassName.getActiveActivity();

To nie jest sposób w jaki DroidFu to robi. DroidFu ustawia aktywną aktywność w onCreate, ale nie uważam, że jest ona bardzo solidna.

+0

Hmm ... to wydaje się bardzo pomocne, ale wydaje się, że nie ma dużo dokumentacji? Nie chciałbym zmienić mojej implementacji na DroidFu i nie wiem jak rozwiązać problem, ponieważ nie jest to "typowy" sposób robienia rzeczy. – Bara

+0

Tak, wygląda na to, że jest to stara opuszczona biblioteka, ale przesłanka wydaje się być dobra. Możesz to zrobić bez korzystania z biblioteki. Zasadniczo obiekt Application śledzi aktywną aktywność (używając onResume). Następnie, gdy jesteś gotowy na powiadomienie adaptera, otrzymasz aktywną aktywność z aplikacji, sprawdź, czy jest to wystąpienie oczekiwanego działania, a jeśli tak, rzuć i powiadom. –

+0

Co to jest kod śledzenia "aktywnej aktywności"? To znaczy, czy powinienem robić coś w stylu CurrentActivity act = new CurrentActivity(); następnie przekazuje akt do klasy Application? – Bara

1

Miałem podobny problem, ponieważ posiadałem czasochłonny wątek sendEmptyMessage dla handler'a, który z kolei nazwał notifyDataSetChanged na ListAdapter. Wszystko działało, dopóki nie zmieniłem orientacji.

Rozwiązałem go, deklarując drugi moduł obsługi w wątku UI i wykonując pierwszy moduł obsługi sendEmptyMessage do tego programu obsługi, który z kolei nazwał notifyDataSetChanged na ListAdapter. Oraz o zadeklarowaniu ListAdapter jako statycznego.

Jestem nowicjuszem, więc nie wiem, czy jest to brzydki rozwiązanie, ale dla mnie ...

Z opisu Jere.Jones Przypuszczam, to działa jak: długi uruchomiony proces sendEmptyMessage do uchwytu ze starej aktywności, która z kolei sendEmptyMessage do uchwytu w nowym działaniu.

Powiązane problemy