我的解決方案: 如果它是正確的*,更新數據和可查看項目,而無需重新繪製整個列表。否則notifyDataSetChanged。
正確 - OLDDATA大小==新的數據的大小,和舊的數據ID和它們的順序==新的數據ID和順序
如何:
/**
* 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;
}
,當然還有:
@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;
}
忽略綁定視圖的最後一個參數(我用它來確定是否需要爲ImageDrawable回收位圖)。
如上所述,'可見'視圖的總數大致是適合屏幕的數量(忽略方向更改等),因此沒有大的記憶方式。
注意自我:mImgView.setImageURI()將更新列表項,但只會更新一次;所以我最好使用mLstVwAdapter.notifyDataSetInvalidated()代替。 – kellogs 2011-11-16 19:55:24
該解決方案有效。但是這隻能用yourListView.getChildAt(index)來完成。並改變視圖。兩種解決方案都可以工 – MobiDev 2013-01-11 06:43:07
@erik可以幫助我在這個http://stackoverflow.com/questions/18312539/update-the-valview-of-item-in-the-listview-android?noredirect=1#comment26873838_18312539 – Developer 2013-08-19 12:34:01