Nachdem ich die Daten für eine einzelne Zeile von a erhalten habe ListView
, möchte ich diese einzelne Zeile aktualisieren.
Momentan benutze ich notifyDataSetChanged();
aber das macht die View
Reaktion sehr langsam. Gibt es noch andere Lösungen?
android
performance
listview
Thizzer
quelle
quelle
newView(...)
den Adapter aufrufe, gibt es mir eine andere Ansicht, die jedoch nicht in die eingefügt wirdlistView
.Wie Romain Guy vor einiger Zeit während der Google I / O-Sitzung erklärte, ist die effizienteste Methode, nur eine Ansicht in einer Listenansicht zu aktualisieren, etwa die folgende (diese aktualisiert die gesamten Ansichtsdaten):
ListView list = getListView(); int start = list.getFirstVisiblePosition(); for(int i=start, j=list.getLastVisiblePosition();i<=j;i++) if(target==list.getItemAtPosition(i)){ View view = list.getChildAt(i-start); list.getAdapter().getView(i, view, list); break; }
Angenommen,
target
ist ein Element des Adapters.Dieser Code ruft die
ListView
aktuell angezeigten Ansichten ab, durchsucht sie und durchsucht das gesuchtetarget
Element mit den angezeigten Ansichtselementen. Wenn sich Ihr Ziel unter diesen befindet, rufen Sie die umschließende Ansicht auf und führen Sie den AdaptergetView
für diese Ansicht aus, um die Anzeige zu aktualisieren.Da eine Randnotiz
invalidate
nicht wie erwartet funktioniert und die Ansicht nicht wie bei getView aktualisiert wird,notifyDataSetChanged
wird die gesamte Liste neu erstellt und schließlichgetview
alle angezeigten Elemente aufgerufen, wasinvalidateViews
sich auch auf eine Reihe auswirkt.Eine letzte Sache ist, dass man auch zusätzliche Leistung erhalten kann, wenn man nur ein Kind einer Zeilenansicht ändern muss und nicht die gesamte Zeile wie dies der
getView
Fall ist. In diesem Fall kann der folgende Code ersetzt werdenlist.getAdapter().getView(i, view, list);
(Beispiel zum Ändern einesTextView
Textes):((TextView)view.findViewById(R.id.myid)).setText("some new text");
Auf Code vertrauen wir.
quelle
Diese einfachere Methode funktioniert gut für mich, und Sie müssen nur den Positionsindex kennen, um die Ansicht zu erhalten:
// mListView is an instance variable private void updateItemAtPosition(int position) { int visiblePosition = mListView.getFirstVisiblePosition(); View view = mListView.getChildAt(position - visiblePosition); mListView.getAdapter().getView(position, view, mListView); }
quelle
Der folgende Code hat bei mir funktioniert. Beachten Sie, dass Sie beim Aufrufen von GetChild () um das erste Element in der Liste versetzen müssen, da es relativ dazu ist.
int iFirst = getFirstVisiblePosition(); int iLast = getLastVisiblePosition(); if ( indexToChange >= numberOfRowsInSection() ) { Log.i( "MyApp", "Invalid index. Row Count = " + numberOfRowsInSection() ); } else { if ( ( index >= iFirst ) && ( index <= iLast ) ) { // get the view at the position being updated - need to adjust index based on first in the list View vw = getChildAt( sysvar_index - iFirst ); if ( null != vw ) { // get the text view for the view TextView tv = (TextView) vw.findViewById(com.android.myapp.R.id.scrollingListRowTextView ); if ( tv != null ) { // update the text, invalidation seems to be automatic tv.setText( "Item = " + myAppGetItem( index ) + ". Index = " + index + ". First = " + iFirst + ". Last = " + iLast ); } } } }
quelle
sysvar_index
bedeutet die Position der Zeile, die Sie aktualisieren möchtenEs gibt noch eine viel effizientere Möglichkeit, wenn sie zu Ihrem Anwendungsfall passt.
Wenn Sie den Status ändern und irgendwie die richtige (durch Kenntnis der Position) aufrufen können, ist
mListView.getAdapter().getView()
dies die effizienteste von allen.Ich kann einen wirklich einfachen Weg zeigen, indem ich eine anonyme innere Klasse in meiner
ListAdapter.getView()
Klasse erstelle . In diesem Beispiel wirdTextView
ein Text "neu" angezeigt, und diese Ansicht wird festgelegt,GONE
wenn auf das Listenelement geklickt wird:@Override public View getView(int position, View convertView, ViewGroup parent) { // assign the view we are converting to a local variable View view = convertView; Object quotation = getItem(position); // first check to see if the view is null. if so, we have to inflate it. if (view == null) view = mInflater.inflate(R.layout.list_item_quotation, parent, false); final TextView newTextView = (TextView) view.findViewById(R.id.newTextView); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mCallbacks != null) mCallbacks.onItemSelected(quotation.id); if (!quotation.isRead()) { servicesSingleton.setQuotationStatusReadRequest(quotation.id); quotation.setStatusRead(); newTextView.setVisibility(View.GONE); } } }); if(quotation.isRead()) newTextView.setVisibility(View.GONE); else newTextView.setVisibility(View.VISIBLE); return view; }
Das Framework verwendet automatisch das richtige
position
und Sie müssen sich vor dem Aufruf darum kümmern, es erneut abzurufengetView
.quelle
Für mich hat folgende Zeile funktioniert:
Arraylist.set (Position, neue ModelClass (Wert));
Adapter.notifyDataSetChanged ();
quelle
Hat jemand die 'Ansichtsansicht' für die Überschreibungsmethode in Betracht gezogen?
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //Update the selected item ((TextView)view.findViewById(R.id.cardText2)).setText("done!"); }
quelle