Sie sollten es auf dem UI-Thread ausführen. Erstellen Sie einen Handler innerhalb des UI-Threads und posten Sie dann Runable darauf
Kirill Kulakov
11
Noch einmal: notifyDataSetChanged () funktioniert zumindest nicht für empfohlene Verwendungspraktiken (lesen Sie nicht veraltet). Wenn Sie Listenansicht, Cursoradapter und Inhaltsanbieter verwenden, versuchen Sie möglicherweise Folgendes: gettLoaderManager (). RestartLoader (). Siehe: stackoverflow.com/a/19657500/1087411 Ich möchte zumindest einige Dokumentationen zu notifyDataSetChanged () sehen. Zu viel in Android bleibt dem Black-Box-Testen überlassen.
Anderson
Wenn notifyDataSetChanged nicht funktioniert, sind Sie derjenige, der es falsch macht
zdarsky.peter
4
notifyDataSetChanged funktioniert nicht immer. Ich bin mir nicht sicher, warum dies umstritten ist. Manchmal müssen Sie listView.setAdapter (Adapter) aufrufen, um die alten Ansichten zu löschen. Siehe auch: stackoverflow.com/a/16261588/153275
1
Ich konnte notifyDataSetChanged nie zum Laufen bringen. Ich konnte deutlich sehen, dass sich die Sammlung, die ich dem Adapter zuführe, geändert hat (Elemente wurden entfernt), aber notifyDataSetChanged hat nie etwas getan. Nicht sicher, ob diese Methode nur kaputt ist?
Dies ist die richtige Antwort, wenn Sie nur die Ansicht neu zeichnen müssen. Zum Beispiel, nachdem eine Benutzeranmeldung erfolgt ist, die weitere Informationen oder Optionen in jeder Ansicht der listView verfügbar machen muss. Das war es, was ich tun musste, also gab ich eine Gegenstimme. Wenn sich die zugrunde liegenden Daten ändern, ist es wahrscheinlich besser, notifyDataSetChanged () zu verwenden.
SBerg413
Eigentlich invalidateViews()in den Quellcodesätzen, mDataChanged = true;also bin ich mir nicht sicher, ob dies zu einer besseren Leistung führt alsnotifyDataSetChanged()
vovahost
Du hast meinen Tag gerettet, Alter!
oskarko
Sie können eine Art von Liste nehmen, die "beobachtbare Liste" ist, ohne dass eine Änderung des Datasets erforderlich ist
Priya
153
Bitte ignorieren Sie alle die invalidate(), invalidateViews(), requestLayout(), ... Antworten auf diese Frage.
Wenn der Aufruf notifyDataSetChanged()nicht funktioniert, helfen auch nicht alle Layoutmethoden. Glauben Sie mir, das ListViewwurde richtig aktualisiert. Wenn Sie den Unterschied nicht finden, müssen Sie überprüfen, woher die Daten in Ihrem Adapter stammen.
Wenn dies nur eine Sammlung ist, die Sie im Speicher behalten, überprüfen Sie, ob Sie die Elemente tatsächlich aus der Sammlung gelöscht oder hinzugefügt haben, bevor Sie die aufrufen notifyDataSetChanged().
Wenn Sie mit einem Datenbank- oder Service-Backend arbeiten, müssen Sie die Methode aufrufen, um die Informationen erneut abzurufen (oder die In-Memory-Daten zu bearbeiten), bevor Sie das aufrufen notifyDataSetChanged().
Die Sache ist, dass dies notifyDataSetChangednur funktioniert, wenn sich der Datensatz geändert hat. Das ist also der richtige Ort, wenn Sie keine Änderungen feststellen. Debuggen Sie bei Bedarf.
ArrayAdapter vs BaseAdapter
Ich habe festgestellt, dass die Arbeit mit einem Adapter, mit dem Sie die Sammlung verwalten können, wie ein BaseAdapter, besser funktioniert. Einige Adapter wie der ArrayAdapter verwalten bereits ihre eigene Sammlung, was es schwieriger macht, zur richtigen Sammlung für Updates zu gelangen. In den meisten Fällen ist es wirklich nur eine unnötige zusätzliche Schwierigkeitsstufe.
UI-Thread
Es ist wahr, dass dies vom UI-Thread aufgerufen werden muss. Andere Antworten enthalten Beispiele, wie dies erreicht werden kann. Dies ist jedoch nur erforderlich, wenn Sie diese Informationen von außerhalb des UI-Threads bearbeiten. Das ist von einem Dienst oder einem Nicht-UI-Thread. In einfachen Fällen aktualisieren Sie Ihre Daten durch einen Klick auf eine Schaltfläche oder eine andere Aktivität / ein anderes Fragment. Also immer noch im UI-Thread. Sie müssen diesen runOnUiTrhead nicht immer einfügen.
Schnelles Beispielprojekt
Kann unter https://github.com/hanscappelle/so-2250770.git gefunden werden . Klonen und öffnen Sie das Projekt einfach in Android Studio (gradle). Dieses Projekt verfügt über ein MainAcitivity-Gebäude ListViewmit allen zufälligen Daten. Diese Liste kann über das Aktionsmenü aktualisiert werden.
Die Adapterimplementierung, die ich für dieses Beispiel ModelObject erstellt habe, macht die Datenerfassung verfügbar
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}
Code aus der Hauptaktivität
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();}}
du liegst falsch. notifyDataSetChanged () hat bei mir nicht funktioniert, aber invalidateViews () hat es richtig gemacht.
Babay
6
Ich habe das Problem, dass sich die tatsächlichen Elemente in der Liste nicht ändern, z. B. die gleiche Anzahl von Elementen. Das Problem ist jedoch, dass sich die Art und Weise, wie sie präsentiert werden, ändern muss. Das bedeutet, dass der Code meines Adapters zum Erstellen der Benutzeroberfläche erneut ausgeführt werden muss und dann ein Element in den Listenzeilen korrekt ausgeblendet werden muss. notifyDataSetChanged () funktioniert nicht ...
Sven Haiges
9
Diese Antwort hat mir wirklich geholfen. Ich habe das Array aus bestimmten Gründen im Speicher behalten. Um das adapter.clear()adapter.addAll(Array<T>)notifyDataSetChanged()
Problem
2
@hcpl, wie soll ich notifyDataSetChanged aufrufen, wenn ich mich im OnClickListener des Adapters für eine CheckBox befinde? invalidateViews erledigt den Job gerade. Warum ist invalidateViews die falsche Methode zum Aufrufen?
Craned
1
Ich konnte notifyDataSetChanged nie zum Laufen bringen. Ich konnte deutlich sehen, dass sich die Sammlung, die ich dem Adapter zuführe, geändert hat (Elemente wurden entfernt), aber notifyDataSetChanged hat nie etwas getan. Nicht sicher, ob diese Methode nur kaputt ist?
bis zum
42
Rufen Sie runnable an, wann immer Sie möchten:
runOnUiThread(run);
OnCreate(), setzen Sie Ihren ausführbaren Thread:
run =newRunnable(){publicvoid run(){//reload content
arraylist.clear();
arraylist.addAll(db.readAll());
adapter.notifyDataSetChanged();
listview.invalidateViews();
listview.refreshDrawableState();}};
Funktioniert auch in meinem Fall, in dem ich eine Listenansicht basierend auf Daten aktualisieren muss, die von einer TCP-Verbindung stammen (von einem "nonUI" -Thread). Die einzige Möglichkeit, die Liste neu zu zeichnen, bestand darin, alle Elemente der ArrayList zu löschen und erneut hinzuzufügen. Wenn Sie sich bereits im UI-Thread befinden, müssen Sie den Code nicht über die runOnUiThread()Funktion aufrufen .
Andre
Vielen Dank! Für mich geht das. Für alle Personen, die dies von einem Fragment aus ausführen möchten, sollten Sie getActivity (). RunOnUiThread (new Runnable ...) verwenden, um sicherzustellen, dass der Code auf dem UI-Thread ausgeführt wird
Codierungspuss
Ich sehe den Zweck nicht run = new Runnable()und habe meiner Funktion nur eine public void refreshUIThread()Methode gegeben, die Ihre run()Methode modelliert (was auch funktioniert).
T. Woody
11
Ich habe einige Probleme mit der dynamischen Aktualisierung meiner Listenansicht.
Rufen Sie notifyDataSetChanged () auf Ihrem Adapter auf.
In diesem Google I / O-Video können einige zusätzliche Details zum Aufrufen von notifyDataSetChanged () angezeigt werden.
notifyDataSetChanged () funktionierte in meinem Fall nicht richtig [Ich habe notifyDataSetChanged von einer anderen Klasse aufgerufen]. Nur für den Fall, dass ich die ListView in der laufenden Aktivität (Thread) bearbeitet habe. Das Video dank Christopher gab den letzten Hinweis.
In meiner zweiten Klasse habe ich verwendet
Runnable run =newRunnable(){publicvoid run(){
contactsActivity.update();}};
contactsActivity.runOnUiThread(run);
um auf das update () aus meiner Aktivität zuzugreifen. Dieses Update enthält
myAdapter.notifyDataSetChanged();
um den Adapter anzuweisen, die Ansicht zu aktualisieren. Hat gut funktioniert, soweit ich sagen kann.
Wenn Sie mit der ListView-Aktualisierung immer noch nicht zufrieden sind, können Sie sich dieses Snippet ansehen. Dies dient zum Laden der listView aus der Datenbank. Sie müssen die ListView lediglich neu laden, nachdem Sie eine CRUD-Operation ausgeführt haben. Dies ist kein bester Weg Code, aber es wird die ListView nach Ihren Wünschen aktualisieren.
Es funktioniert für mich .... wenn Sie eine bessere Lösung finden, teilen Sie bitte ...
....... .......
......
Führen Sie Ihre CRUD-Operationen durch.
......
..... .....
DBAdapter.open ();
DBAdapter.insert_into_SingleList ();
// Bringe diese DB_Ergebnisse und füge sie als Inhalt zur Liste hinzu ....
ls2.setAdapter (neuer ArrayAdapter (DynTABSample.this,
android.R.layout.simple_list_item_1, DBAdapter.DB_ListView));
DBAdapter.close ();
Die von den Personen in diesem Beitrag vorgeschlagenen Lösungen funktionieren oder hängen nicht hauptsächlich von der Android-Version Ihres Geräts ab. Um beispielsweise die AddAll-Methode zu verwenden, müssen Sie android: minSdkVersion = "10" in Ihr Android-Gerät einfügen.
Um diese Fragen für alle Geräte zu lösen, habe ich meine eigene Methode in meinem Adapter erstellt und innerhalb der von ArrayAdapter geerbten Methode zum Hinzufügen und Entfernen verwendet, mit der Sie Ihre Daten problemlos aktualisieren können.
Mein Code: Mit meiner eigenen Datenklasse RaceResult verwenden Sie Ihr eigenes Datenmodell.
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!!!
Sie müssen ein einzelnes Objekt dieser Liste verwenden, dessen Daten Sie aufblasen ListView. Wenn die Referenz notifyDataSetChanged()geändert wird, funktioniert dies nicht. Wenn Sie Elemente aus der Listenansicht löschen, löschen Sie sie auch aus der Liste, die Sie verwenden, unabhängig davon, ob es sich um eine ArrayList <> oder etwas anderes handelt. Rufen Sie dann das
notifyDataSetChanged()Objekt Ihrer Adapterklasse auf.
Also hier sehen Sie, wie ich es in meinem Adapter geschafft habe, siehe unten
Ich konnte notifyDataSetChanged () nicht dazu bringen, an der Aktualisierung meines SimpleAdapter zu arbeiten. Stattdessen habe ich versucht, zuerst alle Ansichten zu entfernen, die mit removeAllViews () an das übergeordnete Layout angehängt wurden, dann die ListView hinzuzufügen, und das hat funktioniert, sodass ich die aktualisieren konnte Benutzeroberfläche:
Für mich konnte nach dem Ändern der Informationen in der SQL-Datenbank nichts die Listenansicht aktualisieren (um eine bestimmte erweiterbare Listenansicht zu sein). Wenn notifyDataSetChanged () nicht hilft, können Sie versuchen, Ihre Liste zuerst zu löschen und sie nach diesem Aufruf notifyDataSetChanged () erneut hinzuzufügen. Zum Beispiel
Ich war das gleiche, als ich in einem Fragment eine ListView (in einer einzelnen TextView) mit der Mac-Adresse von BLE-Geräten füllen wollte, die über einen längeren Zeitraum gescannt wurden.
Ich denke, es hängt davon ab, was Sie unter Aktualisieren verstehen. Meinen Sie damit, dass die GUI-Anzeige aktualisiert werden soll, oder meinen Sie, dass die untergeordneten Ansichten so aktualisiert werden sollen, dass Sie programmgesteuert getChildAt (int) aufrufen und die Ansicht abrufen können, die dem Adapter entspricht.
Wenn Sie möchten, dass die GUI-Anzeige aktualisiert wird, rufen Sie notifyDataSetChanged () auf dem Adapter auf. Die GUI wird beim nächsten Neuzeichnen aktualisiert.
Wenn Sie getChildAt (int) aufrufen und eine Ansicht abrufen möchten, die den Inhalt des Adapters widerspiegelt, rufen Sie layoutChildren () auf. Dadurch wird die untergeordnete Ansicht aus den Adapterdaten rekonstruiert.
Ich hatte eine ArrayList, die ich in einer Listenansicht anzeigen wollte. ArrayList enthielt Elemente aus MySQL. Ich habe die onRefresh-Methode überschrieben und bei dieser Methode tablelayout.removeAllViews () verwendet. und wiederholte dann den Vorgang zum erneuten Abrufen von Daten aus der Datenbank. Stellen Sie jedoch vorher sicher, dass Sie Ihre ArrayList oder eine andere Datenstruktur löschen. Andernfalls werden neue Daten an die alte angehängt.
Wenn Sie die UI-Listenansicht von einem Dienst aus aktualisieren möchten, machen Sie den Adapter in Ihrer Hauptaktivität statisch und gehen Sie folgendermaßen vor:
Wenn Sie mit dem Android - Führungslinien werden und Sie verwenden die ContentProvidersDaten von zu erhalten Databaseund Sie die Anzeige in der ListViewVerwendung der CursorLoaderund CursorAdapters, dann sind Sie alle Änderungen an den zugehörigen Daten werden automatisch in der Listview widerspiegeln.
Ihre getContext().getContentResolver().notifyChange(uri, null);auf dem Cursor in der ContentProviderwird ausreichen, um die Änderungen widerzuspiegeln. Keine zusätzliche Umgehung erforderlich.
Wenn Sie jedoch nicht alle verwenden, müssen Sie dem Adapter mitteilen, wann sich das Dataset ändert. Außerdem müssen Sie Ihren Datensatz neu füllen / neu laden (z. B. Liste) und dann notifyDataSetChanged()den Adapter aufrufen .
notifyDataSetChanged()funktioniert nicht, wenn es keine Änderungen im Datset gibt. Hier ist der Kommentar über der Methode in docs-
/**
* Notifies the attached observers that the underlying data has been changed
* and any View reflecting the data set should refresh itself.
*/
Ich konnte notifyDataSetChanged nur erhalten, indem ich neue Adapterdaten abrief, dann den Adapter für die Listenansicht zurücksetzte und den Aufruf folgendermaßen tätigte:
Wenn ich hier über mein Szenario gesprochen habe, funktioniert keine der oben genannten Antworten, da ich eine Aktivität hatte, die eine Liste von Datenbankwerten zusammen mit einer Löschtaste anzeigt, und wenn eine Löschtaste gedrückt wird, wollte ich dieses Element aus der Liste löschen.
Das Coole war, ich habe keine Recycler-Ansicht verwendet, sondern eine einfache Listenansicht und diese in der Adapterklasse initialisierte Listenansicht. Das Aufrufen von notifyDataSetChanged()wird also innerhalb der Adapterklasse und sogar in der Aktivitätsklasse, in der das Adapterobjekt initialisiert wird, nichts tun, da sich die Löschmethode in der Adapterklasse befand.
Die Lösung bestand also darin, das Objekt in der Adapterklassenmethode aus dem Adapter zu entfernen getView(um nur dieses bestimmte Objekt zu löschen, aber wenn Sie alle löschen möchten, rufen Sie auf clear()).
Um eine Vorstellung davon zu bekommen, wie mein Code aussah,
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}});//....
Hinweis: Hier remove()und getItem()Methoden werden von der Adapterklasse geerbt.
remove() - um das bestimmte Element zu entfernen, auf das geklickt wird
getItem(position) - soll das Element (hier ist das mein Word-Objekt, das ich zur Liste hinzugefügt habe) von der angeklickten Position abrufen.
So setze ich den Adapter auf die Listenansicht in der Aktivitätsklasse,
Antworten:
Rufen Sie
notifyDataSetChanged()
IhrAdapter
Objekt auf, sobald Sie die Daten in diesem Adapter geändert haben.notifyDataSetChanged()
In diesem Google I / O-Video finden Sie einige zusätzliche Informationen dazu, wie / wann Sie anrufen müssen .quelle
Sie können auch Folgendes verwenden:
quelle
invalidateViews()
in den Quellcodesätzen,mDataChanged = true;
also bin ich mir nicht sicher, ob dies zu einer besseren Leistung führt alsnotifyDataSetChanged()
Bitte ignorieren Sie alle die
invalidate()
,invalidateViews()
,requestLayout()
, ... Antworten auf diese Frage.Das Richtige (und glücklicherweise auch als richtige Antwort markiert) ist ,
notifyDataSetChanged()
Ihren Adapter anzurufen .Fehlerbehebung
Wenn der Aufruf
notifyDataSetChanged()
nicht funktioniert, helfen auch nicht alle Layoutmethoden. Glauben Sie mir, dasListView
wurde richtig aktualisiert. Wenn Sie den Unterschied nicht finden, müssen Sie überprüfen, woher die Daten in Ihrem Adapter stammen.Wenn dies nur eine Sammlung ist, die Sie im Speicher behalten, überprüfen Sie, ob Sie die Elemente tatsächlich aus der Sammlung gelöscht oder hinzugefügt haben, bevor Sie die aufrufen
notifyDataSetChanged()
.Wenn Sie mit einem Datenbank- oder Service-Backend arbeiten, müssen Sie die Methode aufrufen, um die Informationen erneut abzurufen (oder die In-Memory-Daten zu bearbeiten), bevor Sie das aufrufen
notifyDataSetChanged()
.Die Sache ist, dass dies
notifyDataSetChanged
nur funktioniert, wenn sich der Datensatz geändert hat. Das ist also der richtige Ort, wenn Sie keine Änderungen feststellen. Debuggen Sie bei Bedarf.ArrayAdapter vs BaseAdapter
Ich habe festgestellt, dass die Arbeit mit einem Adapter, mit dem Sie die Sammlung verwalten können, wie ein BaseAdapter, besser funktioniert. Einige Adapter wie der ArrayAdapter verwalten bereits ihre eigene Sammlung, was es schwieriger macht, zur richtigen Sammlung für Updates zu gelangen. In den meisten Fällen ist es wirklich nur eine unnötige zusätzliche Schwierigkeitsstufe.
UI-Thread
Es ist wahr, dass dies vom UI-Thread aufgerufen werden muss. Andere Antworten enthalten Beispiele, wie dies erreicht werden kann. Dies ist jedoch nur erforderlich, wenn Sie diese Informationen von außerhalb des UI-Threads bearbeiten. Das ist von einem Dienst oder einem Nicht-UI-Thread. In einfachen Fällen aktualisieren Sie Ihre Daten durch einen Klick auf eine Schaltfläche oder eine andere Aktivität / ein anderes Fragment. Also immer noch im UI-Thread. Sie müssen diesen runOnUiTrhead nicht immer einfügen.
Schnelles Beispielprojekt
Kann unter https://github.com/hanscappelle/so-2250770.git gefunden werden . Klonen und öffnen Sie das Projekt einfach in Android Studio (gradle). Dieses Projekt verfügt über ein MainAcitivity-Gebäude
ListView
mit allen zufälligen Daten. Diese Liste kann über das Aktionsmenü aktualisiert werden.Die Adapterimplementierung, die ich für dieses Beispiel ModelObject erstellt habe, macht die Datenerfassung verfügbar
Code aus der Hauptaktivität
Mehr Informationen
Ein weiterer netter Beitrag über die Leistungsfähigkeit von listViews finden Sie hier: http://www.vogella.com/articles/AndroidListView/article.html
quelle
adapter.clear()
adapter.addAll(Array<T>)
notifyDataSetChanged()
Rufen Sie runnable an, wann immer Sie möchten:
OnCreate()
, setzen Sie Ihren ausführbaren Thread:quelle
runOnUiThread()
Funktion aufrufen .run = new Runnable()
und habe meiner Funktion nur einepublic void refreshUIThread()
Methode gegeben, die Ihrerun()
Methode modelliert (was auch funktioniert).Ich habe einige Probleme mit der dynamischen Aktualisierung meiner Listenansicht.
notifyDataSetChanged () funktionierte in meinem Fall nicht richtig [Ich habe notifyDataSetChanged von einer anderen Klasse aufgerufen]. Nur für den Fall, dass ich die ListView in der laufenden Aktivität (Thread) bearbeitet habe. Das Video dank Christopher gab den letzten Hinweis.
In meiner zweiten Klasse habe ich verwendet
um auf das update () aus meiner Aktivität zuzugreifen. Dieses Update enthält
um den Adapter anzuweisen, die Ansicht zu aktualisieren. Hat gut funktioniert, soweit ich sagen kann.
quelle
Wenn Sie SimpleCursorAdapter verwenden , rufen Sie Requery () für das Cursor-Objekt auf.
quelle
Wenn Sie mit der ListView-Aktualisierung immer noch nicht zufrieden sind, können Sie sich dieses Snippet ansehen. Dies dient zum Laden der listView aus der Datenbank. Sie müssen die ListView lediglich neu laden, nachdem Sie eine CRUD-Operation ausgeführt haben. Dies ist kein bester Weg Code, aber es wird die ListView nach Ihren Wünschen aktualisieren.
Es funktioniert für mich .... wenn Sie eine bessere Lösung finden, teilen Sie bitte ...
quelle
Die von den Personen in diesem Beitrag vorgeschlagenen Lösungen funktionieren oder hängen nicht hauptsächlich von der Android-Version Ihres Geräts ab. Um beispielsweise die AddAll-Methode zu verwenden, müssen Sie android: minSdkVersion = "10" in Ihr Android-Gerät einfügen.
Um diese Fragen für alle Geräte zu lösen, habe ich meine eigene Methode in meinem Adapter erstellt und innerhalb der von ArrayAdapter geerbten Methode zum Hinzufügen und Entfernen verwendet, mit der Sie Ihre Daten problemlos aktualisieren können.
Mein Code: Mit meiner eigenen Datenklasse RaceResult verwenden Sie Ihr eigenes Datenmodell.
ResultGpRowAdapter.java
ResultsGp.java
quelle
Wenn Sie Ihre Bildlaufposition beim Aktualisieren beibehalten möchten, können Sie dies tun:
Ausführliche Informationen finden Sie unter Android ListView: Behalten Sie Ihre Bildlaufposition bei, wenn Sie aktualisieren .
quelle
Verwenden Sie einfach
myArrayList.remove(position);
in einem Hörer:quelle
Sie müssen ein einzelnes Objekt dieser Liste verwenden, dessen Daten Sie aufblasen
ListView
. Wenn die ReferenznotifyDataSetChanged()
geändert wird, funktioniert dies nicht. Wenn Sie Elemente aus der Listenansicht löschen, löschen Sie sie auch aus der Liste, die Sie verwenden, unabhängig davon, ob es sich um eine ArrayList <> oder etwas anderes handelt. Rufen Sie dann dasnotifyDataSetChanged()
Objekt Ihrer Adapterklasse auf.Also hier sehen Sie, wie ich es in meinem Adapter geschafft habe, siehe unten
quelle
Nach dem Löschen von Daten aus der Listenansicht müssen Sie anrufen
refreshDrawableState()
. Hier ist das Beispiel:und
deleteContact
Methode in derDatabaseHelper
Klasse wird etwas aussehenquelle
Ich konnte notifyDataSetChanged () nicht dazu bringen, an der Aktualisierung meines SimpleAdapter zu arbeiten. Stattdessen habe ich versucht, zuerst alle Ansichten zu entfernen, die mit removeAllViews () an das übergeordnete Layout angehängt wurden, dann die ListView hinzuzufügen, und das hat funktioniert, sodass ich die aktualisieren konnte Benutzeroberfläche:
quelle
Für mich konnte nach dem Ändern der Informationen in der SQL-Datenbank nichts die Listenansicht aktualisieren (um eine bestimmte erweiterbare Listenansicht zu sein). Wenn notifyDataSetChanged () nicht hilft, können Sie versuchen, Ihre Liste zuerst zu löschen und sie nach diesem Aufruf notifyDataSetChanged () erneut hinzuzufügen. Zum Beispiel
Hoffe es macht Sinn für dich.
quelle
Bei Verwendung von SimpleCursorAdapter kann changeCursor (newCursor) auf dem Adapter aufgerufen werden.
quelle
Ich war das gleiche, als ich in einem Fragment eine ListView (in einer einzelnen TextView) mit der Mac-Adresse von BLE-Geräten füllen wollte, die über einen längeren Zeitraum gescannt wurden.
Was ich getan habe war folgendes:
Dann begann die ListView dynamisch mit der Mac-Adresse der gefundenen Geräte zu füllen.
quelle
Ich denke, es hängt davon ab, was Sie unter Aktualisieren verstehen. Meinen Sie damit, dass die GUI-Anzeige aktualisiert werden soll, oder meinen Sie, dass die untergeordneten Ansichten so aktualisiert werden sollen, dass Sie programmgesteuert getChildAt (int) aufrufen und die Ansicht abrufen können, die dem Adapter entspricht.
Wenn Sie möchten, dass die GUI-Anzeige aktualisiert wird, rufen Sie notifyDataSetChanged () auf dem Adapter auf. Die GUI wird beim nächsten Neuzeichnen aktualisiert.
Wenn Sie getChildAt (int) aufrufen und eine Ansicht abrufen möchten, die den Inhalt des Adapters widerspiegelt, rufen Sie layoutChildren () auf. Dadurch wird die untergeordnete Ansicht aus den Adapterdaten rekonstruiert.
quelle
Ich hatte eine ArrayList, die ich in einer Listenansicht anzeigen wollte. ArrayList enthielt Elemente aus MySQL. Ich habe die onRefresh-Methode überschrieben und bei dieser Methode tablelayout.removeAllViews () verwendet. und wiederholte dann den Vorgang zum erneuten Abrufen von Daten aus der Datenbank. Stellen Sie jedoch vorher sicher, dass Sie Ihre ArrayList oder eine andere Datenstruktur löschen. Andernfalls werden neue Daten an die alte angehängt.
quelle
Wenn Sie die UI-Listenansicht von einem Dienst aus aktualisieren möchten, machen Sie den Adapter in Ihrer Hauptaktivität statisch und gehen Sie folgendermaßen vor:
quelle
Wenn Sie mit dem Android - Führungslinien werden und Sie verwenden die
ContentProviders
Daten von zu erhaltenDatabase
und Sie die Anzeige in derListView
Verwendung derCursorLoader
undCursorAdapters
, dann sind Sie alle Änderungen an den zugehörigen Daten werden automatisch in der Listview widerspiegeln.Ihre
getContext().getContentResolver().notifyChange(uri, null);
auf dem Cursor in derContentProvider
wird ausreichen, um die Änderungen widerzuspiegeln. Keine zusätzliche Umgehung erforderlich.Wenn Sie jedoch nicht alle verwenden, müssen Sie dem Adapter mitteilen, wann sich das Dataset ändert. Außerdem müssen Sie Ihren Datensatz neu füllen / neu laden (z. B. Liste) und dann
notifyDataSetChanged()
den Adapter aufrufen .notifyDataSetChanged()
funktioniert nicht, wenn es keine Änderungen im Datset gibt. Hier ist der Kommentar über der Methode in docs-quelle
Ich konnte notifyDataSetChanged nur erhalten, indem ich neue Adapterdaten abrief, dann den Adapter für die Listenansicht zurücksetzte und den Aufruf folgendermaßen tätigte:
quelle
auf andere Option ist
onWindowFocusChanged
Methode, aber sicher, es ist sensibel und benötigt eine zusätzliche Codierung für wen interessiertquelle
Angenommen, Sie haben eine Liste an Ihren Adapter übergeben.
Verwenden:
list.getAdapter().notifyDataSetChanged()
um deine Liste zu aktualisieren.
quelle
Wenn ich hier über mein Szenario gesprochen habe, funktioniert keine der oben genannten Antworten, da ich eine Aktivität hatte, die eine Liste von Datenbankwerten zusammen mit einer Löschtaste anzeigt, und wenn eine Löschtaste gedrückt wird, wollte ich dieses Element aus der Liste löschen.
Das Coole war, ich habe keine Recycler-Ansicht verwendet, sondern eine einfache Listenansicht und diese in der Adapterklasse initialisierte Listenansicht. Das Aufrufen von
notifyDataSetChanged()
wird also innerhalb der Adapterklasse und sogar in der Aktivitätsklasse, in der das Adapterobjekt initialisiert wird, nichts tun, da sich die Löschmethode in der Adapterklasse befand.Die Lösung bestand also darin, das Objekt in der Adapterklassenmethode aus dem Adapter zu entfernen
getView
(um nur dieses bestimmte Objekt zu löschen, aber wenn Sie alle löschen möchten, rufen Sie aufclear()
).Um eine Vorstellung davon zu bekommen, wie mein Code aussah,
Hinweis: Hier
remove()
undgetItem()
Methoden werden von der Adapterklasse geerbt.remove()
- um das bestimmte Element zu entfernen, auf das geklickt wirdgetItem(position)
- soll das Element (hier ist das mein Word-Objekt, das ich zur Liste hinzugefügt habe) von der angeklickten Position abrufen.So setze ich den Adapter auf die Listenansicht in der Aktivitätsklasse,
quelle
Am einfachsten ist es, einfach einen neuen Adaper zu erstellen und den alten fallen zu lassen:
quelle