Meine Lösung: Wenn es korrekt ist *, aktualisieren Sie die Daten und sichtbaren Elemente, ohne die gesamte Liste neu zu zeichnen. Sonst notifyDataSetChanged.
Correct - olddata Größe == neue Datengröße und alte Daten-IDs und deren Reihenfolge == neue Daten-IDs und Ordnung
Wie:
/**
* A View can only be used (visible) once. This class creates a map from int (position) to view, where the mapping
* is one-to-one and on.
*
*/
private static class UniqueValueSparseArray extends SparseArray<View> {
private final HashMap<View,Integer> m_valueToKey = new HashMap<View,Integer>();
@Override
public void put(int key, View value) {
final Integer previousKey = m_valueToKey.put(value,key);
if(null != previousKey) {
remove(previousKey);//re-mapping
}
super.put(key, value);
}
}
@Override
public void setData(final List<? extends DBObject> data) {
// TODO Implement 'smarter' logic, for replacing just part of the data?
if (data == m_data) return;
List<? extends DBObject> oldData = m_data;
m_data = null == data ? Collections.EMPTY_LIST : data;
if (!updateExistingViews(oldData, data)) notifyDataSetChanged();
else if (DEBUG) Log.d(TAG, "Updated without notifyDataSetChanged");
}
/**
* See if we can update the data within existing layout, without re-drawing the list.
* @param oldData
* @param newData
* @return
*/
private boolean updateExistingViews(List<? extends DBObject> oldData, List<? extends DBObject> newData) {
/**
* Iterate over new data, compare to old. If IDs out of sync, stop and return false. Else - update visible
* items.
*/
final int oldDataSize = oldData.size();
if (oldDataSize != newData.size()) return false;
DBObject newObj;
int nVisibleViews = m_visibleViews.size();
if(nVisibleViews == 0) return false;
for (int position = 0; nVisibleViews > 0 && position < oldDataSize; position++) {
newObj = newData.get(position);
if (oldData.get(position).getId() != newObj.getId()) return false;
// iterate over visible objects and see if this ID is there.
final View view = m_visibleViews.get(position);
if (null != view) {
// this position has a visible view, let's update it!
bindView(position, view, false);
nVisibleViews--;
}
}
return true;
}
und natürlich:
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
final View result = createViewFromResource(position, convertView, parent);
m_visibleViews.put(position, result);
return result;
}
Ignoriere den letzten Parameter für bindView (Ich benutze ihn um festzustellen, ob ich Bitmaps für ImageDrawable recyceln muss).
Wie oben erwähnt, ist die Gesamtzahl der "sichtbaren" Ansichten ungefähr die Menge, die auf den Bildschirm passt (Orientierungsänderungen werden ignoriert usw.), also keine großen Speicher.
Hinweis zu Selbst: mImgView.setImageURI() wird das Listenelement aber nur einmal aktualisieren; Daher ist es besser, stattdessen mstvwAdapter.notifyDataSetInvalidated() zu verwenden. – kellogs
Diese Lösung funktioniert. Dies kann jedoch nur mit yourListView.getChildAt (index); und ändere die Ansicht. Beide Lösungen funktionieren !! – MobiDev
@erik können Sie mir dabei helfen http://stackoverflow.com/questions/18312539/update-the-value-of-item-in-the-listview-android?noredirect=1#comment26873838_18312539 – Developer