Android Short Tips:数据源正常,而ListView显示错乱问题
曾经在使用ListView过程中,遇到过一个小问题:ListView数据源是正常的,但是在显示的时候出现了错乱。相信很多Android开发者都遇到过这个问题。
这个问题的原因很简单,就是ListView Adapter在getView的时候,由于convertView已经存在,没有创建符合类型的特定View。
1 /** 2 * 不同的类型,不同的View,不同的布局 3 * @param type 4 * @return 5 */ 6 private View createView(ListItemViewModelType type) { 7 if (type == ListItemViewModelType.TYPE1) { 8 return new ListType1ItemView(mContext); 9 } else if (type == ListItemViewModelType.TYPE2) { 10 return new ListType2ItemView(mContext); 11 } else if (type == ListItemViewModelType.TYPE3) { 12 return new ListType3ItemView(mContext); 13 } else { 14 return new ListDefaultItemView(mContext); 15 } 16 } 17 18 @Override 19 public View getView(int position, View convertView, ViewGroup parent) { 20 21 if (convertView == null) {// ListView重复利用机制导致convertView 不为null情况存在 22 23 convertView = createView(mDataSource.get(position).getType()); 24 } 25 26 ((ListItemView) convertView).setData(mDataSource.get(position)); 27 28 return convertView; 29 }
ListView出于性能考虑,为尽量让ItemView重用。上面的getView方法,在convertView不为空值时,就没有重新创建,这就导致数据源变化了而UI没有变化,表现出来就是列表错乱。针对这种情况,需要对重用的ItemView设置一个类型依据,用于判断该View是否适用于新的数据源。通常采用的做法就是设置View的tag属性,使用后设置,下次使用前取出判断。
1 @Override 2 public View getView(int position, View convertView, ViewGroup parent) { 3 4 Object tag = convertView != null ? convertView.getTag() : null; 5 6 ListItemViewModelType type = mDataSource.get(position).getType(); 7 8 if (!type.equals(tag)) {// convert 为null,或者tag类型不相符,都重新创建 9 convertView = createView(type); 10 convertView.setTag(type); 11 } 12 13 ((ListItemView) convertView).setData(mDataSource.get(position)); 14 15 return convertView; 16 }
上面这种实现,虽然会损耗部分的性能,但能保证数据表现无误。很好的做到了性能与功能的平衡。
另外,如果数据量比较小,且变化不频繁,也可以每次getView的时候都重新创建,这样逻辑简单,便于维护。具体使用依赖于场景。
浙公网安备 33010602011771号