Solusi saya: Jika benar *, perbarui data dan item yang dapat dilihat tanpa menggambar ulang seluruh daftar. NotifyDataSetChanged lain.
Benar - ukuran oldData == ukuran data baru, dan ID data lama beserta pesanannya == ID data baru dan pesanan
Bagaimana:
/**
* 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;
}
dan tentu saja:
@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;
}
Abaikan param terakhir ke bindView (saya menggunakannya untuk menentukan apakah saya perlu mendaur ulang bitmap untuk ImageDrawable).
Seperti yang disebutkan di atas, jumlah total tampilan 'terlihat' kira-kira jumlah yang sesuai pada layar (mengabaikan perubahan orientasi dll), jadi tidak ada masalah besar dalam hal memori.