วิธีแก้ปัญหาของฉัน: หากถูกต้อง * ให้อัปเดตข้อมูลและรายการที่สามารถดูได้โดยไม่ต้องวาดใหม่ทั้งรายการ ที่อื่น informDataSetChanged
ถูกต้อง - oldData size == ขนาดข้อมูลใหม่และ ID ข้อมูลเก่าและลำดับ == รหัสข้อมูลใหม่และลำดับ
อย่างไร:
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);
}
super.put(key, value);
}
}
@Override
public void setData(final List<? extends DBObject> 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");
}
private boolean updateExistingViews(List<? extends DBObject> oldData, List<? extends DBObject> newData) {
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;
final View view = m_visibleViews.get(position);
if (null != view) {
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;
}
ละเว้นพารามิเตอร์สุดท้ายของ bindView (ฉันใช้มันเพื่อพิจารณาว่าฉันจำเป็นต้องรีไซเคิลบิตแมปสำหรับ ImageDrawable หรือไม่)
ดังที่ได้กล่าวไว้ข้างต้นจำนวนมุมมองที่ 'มองเห็นได้' ทั้งหมดเป็นจำนวนโดยประมาณที่พอดีกับหน้าจอ (ไม่สนใจการเปลี่ยนแปลงการวางแนว ฯลฯ ) ดังนั้นจึงไม่ต้องใช้หน่วยความจำขนาดใหญ่