Powinieneś uruchomić go w wątku interfejsu użytkownika. Utwórz moduł obsługi w wątku interfejsu użytkownika, a następnie opublikuj w nim Runable
Kirill Kulakov
11
Jeszcze raz: powiadomienieDataSetChanged () nie działa, przynajmniej nie w przypadku praktyk użytkowania, które są zalecane (czytaj nieaktualne). Jeśli korzystasz z widoku listy, adaptera kursora i dostawcy treści, możesz spróbować czegoś podobnego: gettLoaderManager (). RestartLoader (). Zobacz: stackoverflow.com/a/19657500/1087411 Chciałbym zobaczyć co najmniej trochę dokumentacji dotyczącej notyfikacjiDataSetChanged (). Zbyt wiele w Androidzie pozostało do testowania czarnej skrzynki.
Anderson
Jeśli powiadomienieDataSetChanged nie działa, to ty robisz to źle
zdarsky.peter
4
replaceDataSetChanged nie zawsze działa. Nie jestem pewien, dlaczego tak jest. Czasami musisz wywołać listView.setAdapter (adapter), aby wyczyścić stare widoki. Zobacz także: stackoverflow.com/a/16261588/153275
1
Nigdy nie byłem w stanie uzyskać powiadomieniaDataSetChanged. Widziałem wyraźnie, że kolekcja, którą przekazuję do adaptera, uległa zmianie (elementy zostały usunięte), ale powiadomienieDataSetChanged nigdy nic nie zrobiło. Nie jesteś pewien, czy ta metoda jest po prostu zepsuta?
To jest prawidłowa odpowiedź, jeśli wystarczy WYRÓŻNIĆ widok. Na przykład po zalogowaniu użytkownika, który musi ujawnić więcej informacji lub opcji w każdym widoku widoku listy. Właśnie to musiałem zrobić, więc oddałem głos. Jeśli podstawowe dane ulegną zmianie, prawdopodobnie lepszym pomysłem jest skorzystanie z replaceDataSetChanged ().
SBerg413,
Właściwie invalidateViews()w zestawach kodów źródłowych, mDataChanged = true;więc nie jestem pewien, czy to spowoduje lepszą wydajność w porównaniu donotifyDataSetChanged()
vovahost
Uratowałeś mi dzień, stary!
oskarko
możesz wybrać rodzaj listy, która jest „listą obserwowalną”, nie trzeba zmieniać powiadomień
Priya
153
Proszę ignorować wszystkich invalidate(), invalidateViews(), requestLayout()... odpowiedź na to pytanie.
Jeśli wywołanie notifyDataSetChanged()nie działa, wszystkie metody układu również nie pomogą. Uwierz mi, że ListViewzostał odpowiednio zaktualizowany. Jeśli nie znajdziesz różnicy, musisz sprawdzić, skąd pochodzą dane w karcie.
Jeśli jest to tylko kolekcja, którą przechowujesz w pamięci, sprawdź, czy faktycznie ją usunąłeś lub dodałeś do kolekcji przed wywołaniem notifyDataSetChanged().
Jeśli pracujesz z bazą danych lub zapleczem usługi, musisz wywołać metodę, aby ponownie pobrać informacje (lub manipulować danymi w pamięci) przed wywołaniem notifyDataSetChanged().
Chodzi o to, że notifyDataSetChangeddziała to tylko wtedy, gdy zestaw danych się zmienił. To jest miejsce, w którym należy sprawdzić, czy nie zauważysz zmian. W razie potrzeby debuguj.
ArrayAdapter vs BaseAdapter
Odkryłem, że praca z adapterem, który pozwala zarządzać kolekcją, tak jak BaseAdapter działa lepiej. Niektóre adaptery, takie jak ArrayAdapter, już zarządzają własną kolekcją, co utrudnia dostęp do odpowiedniej kolekcji w celu aktualizacji. W większości przypadków jest to po prostu niepotrzebna dodatkowa warstwa trudności.
Wątek interfejsu użytkownika
Prawdą jest, że należy to wywołać z wątku interfejsu użytkownika. Inne odpowiedzi zawierają przykłady, jak to osiągnąć. Jest to jednak wymagane tylko w przypadku pracy z tymi informacjami spoza wątku interfejsu użytkownika. To jest z usługi lub wątku innego niż interfejs użytkownika. W prostych przypadkach będziesz aktualizować swoje dane za pomocą kliknięcia przycisku lub innej aktywności / fragmentu. Więc nadal w wątku interfejsu użytkownika. Nie trzeba zawsze otwierać tego runOnUiTrhead.
Szybki przykładowy projekt
Można znaleźć na https://github.com/hanscappelle/so-2250770.git . Wystarczy sklonować i otworzyć projekt w Android Studio (stopień). Ten projekt ma MainAciency budujący ListViewwszystkie losowe dane. Tę listę można odświeżyć za pomocą menu akcji.
Implementacja adaptera utworzona dla tego przykładu ModelObject udostępnia kolekcję danych
publicclassMyListAdapterextendsBaseAdapter{/**
* this is our own collection of data, can be anything we
* want it to be as long as we get the abstract methods
* implemented using this data and work on this data
* (see getter) you should be fine
*/privateList<ModelObject> mData;/**
* our ctor for this adapter, we'll accept all the things
* we need here
*
* @param mData
*/publicMyListAdapter(finalContext context,finalList<ModelObject> mData){this.mData = mData;this.mContext = context;}publicList<ModelObject> getData(){return mData;}// implement all abstract methods here}
Kod z MainActivity
publicclassMainActivityextendsActivity{privateMyListAdapter mAdapter;@Overrideprotectedvoid onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);ListView list =(ListView) findViewById(R.id.list);// create some dummy data hereList<ModelObject> objects = getRandomData();// and put it into an adapter for the list
mAdapter =newMyListAdapter(this, objects);
list.setAdapter(mAdapter);// mAdapter is available in the helper methods below and the // data will be updated based on action menu interactions// you could also keep the reference to the android ListView // object instead and use the {@link ListView#getAdapter()} // method instead. However you would have to cast that adapter // to your own instance every time}/**
* helper to show what happens when all data is new
*/privatevoid reloadAllData(){// get new modified random dataList<ModelObject> objects = getRandomData();// update data in our adapter
mAdapter.getData().clear();
mAdapter.getData().addAll(objects);// fire the event
mAdapter.notifyDataSetChanged();}/**
* helper to show how only changing properties of data
* elements also works
*/privatevoid scrambleChecked(){Random random =newRandom();// update data in our adapter, iterate all objects and // resetting the checked optionfor(ModelObject mo : mAdapter.getData()){
mo.setChecked(random.nextBoolean());}// fire the event
mAdapter.notifyDataSetChanged();}}
jesteś w błędzie. powiadomienieDataSetChanged () nie działało dla mnie, ale funkcja validateViews () zrobiła to poprawnie.
babay
6
Mam problem polegający na tym, że rzeczywiste elementy na liście się nie zmieniają, np. Ta sama ilość elementów. Problem polega jednak na tym, że sposób ich prezentacji musi ulec zmianie. Oznacza to, że kod mojego adaptera do zbudowania interfejsu użytkownika musi zostać ponownie uruchomiony, a następnie poprawnie ukryć jakiś element w wierszach listy. powiadomienieDataSetChanged () nie działa ...
Sven Haiges
9
Ta odpowiedź naprawdę mi pomogła. Trzymałem tablicę w pamięci z pewnych powodów. Aby to naprawić, teraz dzwonię adapter.clear(), a adapter.addAll(Array<T>)przed dzwonieniemnotifyDataSetChanged()
Michael DePhillips
2
@hcpl, jak powinienem wywołać powiadomienieDataSetChanged, jeśli jestem w OnClickListener adaptera dla CheckBox? invalidateViews właśnie wykonuje zadanie. Dlaczego unieważnia Wyświetla niewłaściwą metodę wywołania?
ściągnął
1
Nigdy nie byłem w stanie uzyskać powiadomieniaDataSetChanged. Widziałem wyraźnie, że kolekcja, którą przekazuję do adaptera, uległa zmianie (elementy zostały usunięte), ale powiadomienieDataSetChanged nigdy nic nie zrobiło. Nie jesteś pewien, czy ta metoda jest po prostu zepsuta?
byemute,
42
Dzwoń w dowolnym momencie:
runOnUiThread(run);
OnCreate(), ustawiasz wątek uruchamialny:
run =newRunnable(){publicvoid run(){//reload content
arraylist.clear();
arraylist.addAll(db.readAll());
adapter.notifyDataSetChanged();
listview.invalidateViews();
listview.refreshDrawableState();}};
Działa również w moim przypadku, w którym muszę zaktualizować widok listy na podstawie danych pochodzących z połączenia TCP (z wątku „nonUI”). Jedynym sposobem na odświeżenie listy było wyczyszczenie i ponowne dodanie wszystkich elementów ArrayList. W każdym razie, jeśli jesteś już w wątku interfejsu, nie musisz wywoływać kodu za pomocą runOnUiThread()funkcji.
Andre
Dzięki! Mi to pasuje. Dla wszystkich ludzi, którzy chcą uruchomić to z fragmentu, powinieneś użyć getActivity (). RunOnUiThread (nowy Runnable ... aby upewnić się, że kod działa w wątku interfejsu użytkownika
codingpuss
Nie widzę celu run = new Runnable()i po prostu nadałem mojej funkcji public void refreshUIThread()metodę, która modeluje twoją run()metodę (która też działa).
T.Woody,
11
Mam problemy z dynamicznym odświeżaniem widoku listy.
Wywołaj powiadomienieDataSetChanged () na karcie.
Niektóre dodatkowe informacje na temat tego, jak / kiedy wywołać powiadomienieDataSetChanged () można obejrzeć w tym filmie Google I / O.
powiadomienieDataSetChanged () nie działało poprawnie w moim przypadku [wywołałem powiadomienieDataSetChanged z innej klasy]. Właśnie w przypadku, gdy edytowałem ListView w działającym działaniu (wątku). Ten film dzięki Christopherowi dał ostatnią wskazówkę.
W mojej drugiej klasie korzystałem
Runnable run =newRunnable(){publicvoid run(){
contactsActivity.update();}};
contactsActivity.runOnUiThread(run);
aby uzyskać dostęp do aktualizacji () z mojej Aktywności. Ta aktualizacja obejmuje
myAdapter.notifyDataSetChanged();
powiedzieć adapterowi, aby odświeżył widok. Działało dobrze, o ile mogę powiedzieć.
jeśli nadal nie jesteś zadowolony z ListView Refreshment, możesz spojrzeć na ten fragment kodu, służy on do wczytywania listView z bazy danych. Właściwie to po prostu przeładuj ListView po wykonaniu jakiejkolwiek operacji CRUD. Nie jest to najlepszy sposób na kod, ale odświeży ListView, jak chcesz ..
Działa dla mnie .... jeśli znajdziesz lepsze rozwiązanie, udostępnij ...
.......
......
wykonaj swoje operacje CRUD ..
......
.....
DBAdapter.open ();
DBAdapter.insert_into_SingleList ();
// Przynieś wyniki DB_result i dodaj go do listy jako jego zawartość ....
ls2.setAdapter (nowy ArrayAdapter (DynTABSample.this,
android.R.layout.simple_list_item_1, DBAdapter.DB_ListView));
DBAdapter.close ();
Rozwiązania zaproponowane przez ludzi w tym poście działają lub nie, głównie w zależności od wersji Androida urządzenia. Na przykład, aby użyć metody AddAll, musisz umieścić Androida: minSdkVersion = "10" na urządzeniu z Androidem.
Aby rozwiązać te pytania dla wszystkich urządzeń, utworzyłem własną metodę w adapterze i używam wewnątrz metody dodawania i usuwania dziedziczenia z ArrayAdapter, które aktualizują dane bez problemów.
Mój kod: Używając własnej klasy danych RaceResult, korzystasz z własnego modelu danych.
ResultGpRowAdapter.java
publicclassResultGpRowAdapterextendsArrayAdapter<RaceResult>{Context context;int resource;List<RaceResult> data=null;publicResultGpRowAdapter(Context context,int resource,List<RaceResult> objects){super(context, resource, objects);this.context = context;this.resource = resource;this.data = objects;}@OverridepublicView getView(int position,View convertView,ViewGroup parent){........}//my own method to populate data publicvoid myAddAll(List<RaceResult> items){for(RaceResult item:items){super.add(item);}}
ResultsGp.java
publicclassResultsGpextendsActivity{@Overrideprotectedvoid onCreate(Bundle savedInstanceState){......................ListView list =(ListView)findViewById(R.id.resultsGpList);ResultGpRowAdapter adapter =newResultGpRowAdapter(this, R.layout.activity_result_gp_row,newArrayList<RaceResult>());//Empty data
list.setAdapter(adapter);............//LOAD a ArrayList<RaceResult> with dataArrayList<RaceResult> data =newArrayList<RaceResult>();
data.add(newRaceResult(....));
data.add(newRaceResult(....));.......
adapter.myAddAll(data);//Your list will be udpdated!!!
Musisz użyć jednego obiektu z tej listy, do którego danych chcesz nadmuchać ListView. Jeśli odwołanie jest zmieniane, to notifyDataSetChanged()nie działa. Za każdym razem, gdy usuwasz elementy z widoku listy, usuwaj je również z używanej listy, niezależnie od tego, czy jest to ArrayList <>, czy coś innego niż Wywołaj
notifyDataSetChanged()obiekt klasy adaptera.
Zobacz więc, jak zarządzałem w mojej przejściówce, patrz poniżej
Nie byłem w stanie uzyskać powiadomieniaDataSetChanged () do pracy nad aktualizacją mojego SimpleAdapter, więc zamiast tego próbowałem najpierw usunąć wszystkie widoki, które zostały dołączone do układu nadrzędnego za pomocą removeAllViews (), a następnie dodać ListView i działało, pozwalając mi zaktualizować Interfejs użytkownika:
Dla mnie po zmianie informacji w bazie danych SQL nic nie może odświeżyć widoku listy (a konkretnie rozwijanego widoku listy), więc jeśli powiadomienieataDataSetChanged () nie pomoże, możesz spróbować wyczyścić listę i dodać ją ponownie po tym wywołaniu powiadomićDataSetChanged (). Na przykład
Myślę, że to zależy od tego, co masz na myśli przez odświeżenie. Czy masz na myśli, że ekran GUI powinien zostać odświeżony, czy masz na myśli, że widoki potomne powinny zostać odświeżone, abyś mógł programowo wywołać getChildAt (int) i uzyskać widok odpowiadający temu, co jest w adapterze.
Jeśli chcesz odświeżyć ekran GUI, wywołaj powiadomienieataDataSetChanged () na adapterze. GUI zostanie odświeżony przy następnym przerysowaniu.
Jeśli chcesz mieć możliwość wywołania getChildAt (int) i uzyskania widoku odzwierciedlającego to, co jest w adapterze, to wywołaj layoutChildren (). Spowoduje to zrekonstruowanie widoku potomnego na podstawie danych adaptera.
Miałem ArrayList, który chciałem wyświetlić w widoku listy. ArrayList zawierał elementy z mysql. Przesłoniłem metodę onRefresh iw tej metodzie użyłem tablelayout.removeAllViews (); a następnie powtórzył proces ponownego pobierania danych z bazy danych. Ale przed tym upewnij się, że wyczyściłeś ArrayList lub jakąkolwiek strukturę danych, albo nowe dane zostaną dołączone do starej.
Jeśli korzystasz z linii prowadzących Androida i używasz ContentProvidersdo pobierania danych Databasei wyświetlasz je za ListViewpomocą CursorLoaderiCursorAdapters , wtedy wszystkie zmiany w powiązanych danych zostaną automatycznie odzwierciedlone w ListView.
Twój getContext().getContentResolver().notifyChange(uri, null);kursor wContentProvider będzie wystarczający, aby odzwierciedlić zmiany. Nie musisz wykonywać dodatkowej pracy.
Ale jeśli nie używasz ich wszystkich, musisz poinformować adapter o zmianie zestawu danych. Musisz również ponownie wypełnić / ponownie załadować zestaw danych (powiedzmy listę), a następnie musisz zadzwonićnotifyDataSetChanged() adapter.
notifyDataSetChanged()nie będzie działać, jeśli nie ma zmian w zestawie danych. Oto komentarz nad metodą w dokumentach
/**
* Notifies the attached observers that the underlying data has been changed
* and any View reflecting the data set should refresh itself.
*/
Byłem w stanie uzyskać powiadomienieDataSetChanged tylko poprzez pobranie nowych danych adaptera, a następnie zresetowanie adaptera do widoku listy, a następnie wykonanie połączenia w następujący sposób:
Jeśli mówiłem tutaj o moim scenariuszu, żadne z powyższych odpowiedzi nie zadziałałoby, ponieważ miałem aktywność, która pokazuje listę wartości db wraz z przyciskiem usuwania, a kiedy przycisk usuwania jest naciśnięty, chciałem usunąć ten element z listy.
Fajne było to, że nie użyłem widoku programu do recyklingu, ale prosty widok listy i ten widok listy zainicjowano w klasie adaptera. Więc dzwoniąc donotifyDataSetChanged() nie spowoduje nic wewnątrz klasy adaptera, a nawet w klasie aktywności, w której inicjowany jest obiekt adaptera, ponieważ metoda usuwania była w klasie adaptera.
Rozwiązaniem było więc usunięcie obiektu z adaptera w getViewmetodzie klasy adaptera (aby usunąć tylko ten konkretny obiekt, ale jeśli chcesz usunąć wszystko, wywołajclear() ).
Aby dowiedzieć się, jak wyglądał mój kod,
publicclassWordAdapterextendsArrayAdapter<Word>{Context context;publicWordAdapter(Activity context,ArrayList<Word> words){}//.......@NonNull@OverridepublicView getView(finalint position,View convertView,ViewGroupgroup){//.......ImageButton deleteBt = listItemView.findViewById(R.id.word_delete_bt);
deleteBt.setOnClickListener(newView.OnClickListener(){@Overridepublicvoid onClick(View v){if(vocabDb.deleteWord(currentWord.id)){//.....}else{//.....}remove(getItem(position));// <---- here is the trick ---<//clear() // if you want to clear everything}});//....
Uwaga: tutaj remove()i getItem()metody są dziedziczone z klasy Adapter.
remove() - aby usunąć konkretny kliknięty element
getItem(position) - ma pobrać element (tutaj, to mój obiekt Word, który dodałem do listy) z klikniętej pozycji.
W ten sposób ustawiam adapter na widok listy w klasie aktywności,
Odpowiedzi:
Zadzwoń
notifyDataSetChanged()
naAdapter
obiekcie Po zmodyfikowaniu danych w tym adapterem.Niektóre dodatkowe informacje na temat tego, jak / kiedy zadzwonić,
notifyDataSetChanged()
można obejrzeć w tym filmie We / Wy Google .źródło
Możesz także użyć tego:
źródło
invalidateViews()
w zestawach kodów źródłowych,mDataChanged = true;
więc nie jestem pewien, czy to spowoduje lepszą wydajność w porównaniu donotifyDataSetChanged()
Proszę ignorować wszystkich
invalidate()
,invalidateViews()
,requestLayout()
... odpowiedź na to pytanie.Właściwą czynnością (i na szczęście oznaczoną również jako prawidłową odpowiedź) jest zadzwonienie do
notifyDataSetChanged()
adaptera .Rozwiązywanie problemów
Jeśli wywołanie
notifyDataSetChanged()
nie działa, wszystkie metody układu również nie pomogą. Uwierz mi, żeListView
został odpowiednio zaktualizowany. Jeśli nie znajdziesz różnicy, musisz sprawdzić, skąd pochodzą dane w karcie.Jeśli jest to tylko kolekcja, którą przechowujesz w pamięci, sprawdź, czy faktycznie ją usunąłeś lub dodałeś do kolekcji przed wywołaniem
notifyDataSetChanged()
.Jeśli pracujesz z bazą danych lub zapleczem usługi, musisz wywołać metodę, aby ponownie pobrać informacje (lub manipulować danymi w pamięci) przed wywołaniem
notifyDataSetChanged()
.Chodzi o to, że
notifyDataSetChanged
działa to tylko wtedy, gdy zestaw danych się zmienił. To jest miejsce, w którym należy sprawdzić, czy nie zauważysz zmian. W razie potrzeby debuguj.ArrayAdapter vs BaseAdapter
Odkryłem, że praca z adapterem, który pozwala zarządzać kolekcją, tak jak BaseAdapter działa lepiej. Niektóre adaptery, takie jak ArrayAdapter, już zarządzają własną kolekcją, co utrudnia dostęp do odpowiedniej kolekcji w celu aktualizacji. W większości przypadków jest to po prostu niepotrzebna dodatkowa warstwa trudności.
Wątek interfejsu użytkownika
Prawdą jest, że należy to wywołać z wątku interfejsu użytkownika. Inne odpowiedzi zawierają przykłady, jak to osiągnąć. Jest to jednak wymagane tylko w przypadku pracy z tymi informacjami spoza wątku interfejsu użytkownika. To jest z usługi lub wątku innego niż interfejs użytkownika. W prostych przypadkach będziesz aktualizować swoje dane za pomocą kliknięcia przycisku lub innej aktywności / fragmentu. Więc nadal w wątku interfejsu użytkownika. Nie trzeba zawsze otwierać tego runOnUiTrhead.
Szybki przykładowy projekt
Można znaleźć na https://github.com/hanscappelle/so-2250770.git . Wystarczy sklonować i otworzyć projekt w Android Studio (stopień). Ten projekt ma MainAciency budujący
ListView
wszystkie losowe dane. Tę listę można odświeżyć za pomocą menu akcji.Implementacja adaptera utworzona dla tego przykładu ModelObject udostępnia kolekcję danych
Kod z MainActivity
Więcej informacji
Kolejny fajny post o sile listViews znajduje się tutaj: http://www.vogella.com/articles/AndroidListView/article.html
źródło
adapter.clear()
, aadapter.addAll(Array<T>)
przed dzwonieniemnotifyDataSetChanged()
Dzwoń w dowolnym momencie:
OnCreate()
, ustawiasz wątek uruchamialny:źródło
runOnUiThread()
funkcji.run = new Runnable()
i po prostu nadałem mojej funkcjipublic void refreshUIThread()
metodę, która modeluje twojąrun()
metodę (która też działa).Mam problemy z dynamicznym odświeżaniem widoku listy.
powiadomienieDataSetChanged () nie działało poprawnie w moim przypadku [wywołałem powiadomienieDataSetChanged z innej klasy]. Właśnie w przypadku, gdy edytowałem ListView w działającym działaniu (wątku). Ten film dzięki Christopherowi dał ostatnią wskazówkę.
W mojej drugiej klasie korzystałem
aby uzyskać dostęp do aktualizacji () z mojej Aktywności. Ta aktualizacja obejmuje
powiedzieć adapterowi, aby odświeżył widok. Działało dobrze, o ile mogę powiedzieć.
źródło
Jeśli używasz SimpleCursorAdapter, spróbuj wywołać requery () na obiekcie Cursor.
źródło
jeśli nadal nie jesteś zadowolony z ListView Refreshment, możesz spojrzeć na ten fragment kodu, służy on do wczytywania listView z bazy danych. Właściwie to po prostu przeładuj ListView po wykonaniu jakiejkolwiek operacji CRUD. Nie jest to najlepszy sposób na kod, ale odświeży ListView, jak chcesz ..
Działa dla mnie .... jeśli znajdziesz lepsze rozwiązanie, udostępnij ...
źródło
Rozwiązania zaproponowane przez ludzi w tym poście działają lub nie, głównie w zależności od wersji Androida urządzenia. Na przykład, aby użyć metody AddAll, musisz umieścić Androida: minSdkVersion = "10" na urządzeniu z Androidem.
Aby rozwiązać te pytania dla wszystkich urządzeń, utworzyłem własną metodę w adapterze i używam wewnątrz metody dodawania i usuwania dziedziczenia z ArrayAdapter, które aktualizują dane bez problemów.
Mój kod: Używając własnej klasy danych RaceResult, korzystasz z własnego modelu danych.
ResultGpRowAdapter.java
ResultsGp.java
źródło
Jeśli chcesz zachować pozycję przewijania podczas odświeżania i możesz to zrobić:
Aby uzyskać szczegółowe informacje, zobacz Android ListView: Utrzymaj pozycję przewijania podczas odświeżania .
źródło
Wystarczy użyć
myArrayList.remove(position);
wewnątrz detektora:źródło
Musisz użyć jednego obiektu z tej listy, do którego danych chcesz nadmuchać
ListView
. Jeśli odwołanie jest zmieniane, tonotifyDataSetChanged()
nie działa. Za każdym razem, gdy usuwasz elementy z widoku listy, usuwaj je również z używanej listy, niezależnie od tego, czy jest to ArrayList <>, czy coś innego niż WywołajnotifyDataSetChanged()
obiekt klasy adaptera.Zobacz więc, jak zarządzałem w mojej przejściówce, patrz poniżej
źródło
Po usunięciu danych z widoku listy musisz zadzwonić
refreshDrawableState()
. Oto przykład:i
deleteContact
metoda wDatabaseHelper
klasie będzie wyglądać niecoźródło
Nie byłem w stanie uzyskać powiadomieniaDataSetChanged () do pracy nad aktualizacją mojego SimpleAdapter, więc zamiast tego próbowałem najpierw usunąć wszystkie widoki, które zostały dołączone do układu nadrzędnego za pomocą removeAllViews (), a następnie dodać ListView i działało, pozwalając mi zaktualizować Interfejs użytkownika:
źródło
Dla mnie po zmianie informacji w bazie danych SQL nic nie może odświeżyć widoku listy (a konkretnie rozwijanego widoku listy), więc jeśli powiadomienieataDataSetChanged () nie pomoże, możesz spróbować wyczyścić listę i dodać ją ponownie po tym wywołaniu powiadomićDataSetChanged (). Na przykład
Mam nadzieję, że ma to dla ciebie sens.
źródło
podczas korzystania z SimpleCursorAdapter może wywoływać changeCursor (newCursor) na adapterze.
źródło
Byłem taki sam, gdy fragmentem chciałem wypełnić ListView (w pojedynczym TextView) adresem MAC urządzeń BLE skanowanych przez pewien czas.
Zrobiłem to:
Następnie ListView zaczął dynamicznie wypełniać adres mac znalezionych urządzeń.
źródło
Myślę, że to zależy od tego, co masz na myśli przez odświeżenie. Czy masz na myśli, że ekran GUI powinien zostać odświeżony, czy masz na myśli, że widoki potomne powinny zostać odświeżone, abyś mógł programowo wywołać getChildAt (int) i uzyskać widok odpowiadający temu, co jest w adapterze.
Jeśli chcesz odświeżyć ekran GUI, wywołaj powiadomienieataDataSetChanged () na adapterze. GUI zostanie odświeżony przy następnym przerysowaniu.
Jeśli chcesz mieć możliwość wywołania getChildAt (int) i uzyskania widoku odzwierciedlającego to, co jest w adapterze, to wywołaj layoutChildren (). Spowoduje to zrekonstruowanie widoku potomnego na podstawie danych adaptera.
źródło
Miałem ArrayList, który chciałem wyświetlić w widoku listy. ArrayList zawierał elementy z mysql. Przesłoniłem metodę onRefresh iw tej metodzie użyłem tablelayout.removeAllViews (); a następnie powtórzył proces ponownego pobierania danych z bazy danych. Ale przed tym upewnij się, że wyczyściłeś ArrayList lub jakąkolwiek strukturę danych, albo nowe dane zostaną dołączone do starej.
źródło
Jeśli chcesz zaktualizować widok listy interfejsu użytkownika z usługi, ustaw statyczny adapter w działaniu głównym i wykonaj następujące czynności:
źródło
Jeśli korzystasz z linii prowadzących Androida i używasz
ContentProviders
do pobierania danychDatabase
i wyświetlasz je zaListView
pomocąCursorLoader
iCursorAdapters
, wtedy wszystkie zmiany w powiązanych danych zostaną automatycznie odzwierciedlone w ListView.Twój
getContext().getContentResolver().notifyChange(uri, null);
kursor wContentProvider
będzie wystarczający, aby odzwierciedlić zmiany. Nie musisz wykonywać dodatkowej pracy.Ale jeśli nie używasz ich wszystkich, musisz poinformować adapter o zmianie zestawu danych. Musisz również ponownie wypełnić / ponownie załadować zestaw danych (powiedzmy listę), a następnie musisz zadzwonić
notifyDataSetChanged()
adapter.notifyDataSetChanged()
nie będzie działać, jeśli nie ma zmian w zestawie danych. Oto komentarz nad metodą w dokumentachźródło
Byłem w stanie uzyskać powiadomienieDataSetChanged tylko poprzez pobranie nowych danych adaptera, a następnie zresetowanie adaptera do widoku listy, a następnie wykonanie połączenia w następujący sposób:
źródło
drugą opcją jest
onWindowFocusChanged
metoda, ale pewna, że jest wrażliwa i wymaga dodatkowego kodowania dla kogo jest zainteresowanaźródło
Rozważ, że przekazałeś listę do adaptera.
Posługiwać się:
list.getAdapter().notifyDataSetChanged()
zaktualizować listę.
źródło
Jeśli mówiłem tutaj o moim scenariuszu, żadne z powyższych odpowiedzi nie zadziałałoby, ponieważ miałem aktywność, która pokazuje listę wartości db wraz z przyciskiem usuwania, a kiedy przycisk usuwania jest naciśnięty, chciałem usunąć ten element z listy.
Fajne było to, że nie użyłem widoku programu do recyklingu, ale prosty widok listy i ten widok listy zainicjowano w klasie adaptera. Więc dzwoniąc do
notifyDataSetChanged()
nie spowoduje nic wewnątrz klasy adaptera, a nawet w klasie aktywności, w której inicjowany jest obiekt adaptera, ponieważ metoda usuwania była w klasie adaptera.Rozwiązaniem było więc usunięcie obiektu z adaptera w
getView
metodzie klasy adaptera (aby usunąć tylko ten konkretny obiekt, ale jeśli chcesz usunąć wszystko, wywołajclear()
).Aby dowiedzieć się, jak wyglądał mój kod,
Uwaga: tutaj
remove()
igetItem()
metody są dziedziczone z klasy Adapter.remove()
- aby usunąć konkretny kliknięty elementgetItem(position)
- ma pobrać element (tutaj, to mój obiekt Word, który dodałem do listy) z klikniętej pozycji.W ten sposób ustawiam adapter na widok listy w klasie aktywności,
źródło
Najłatwiej jest po prostu zrobić nowego Adapera i upuścić starego:
źródło