关于在ListView中显示两种布局时,某次曾经出现过ViewHolder的类转换异常。解决方法是在convertView不为null时,进行holder与type的判断,如果不匹配,则将convertView设置为null。
if ((convertView != null && convertView.getTag() instanceof ViewHolder1 && type == TYPE_2)
||(convertView != null && convertView.getTag() instanceof ViewHolder2 && type == TYPE_1)) {
convertView = null;
}
可是这次写新的demo并没有出现这种情况。相关实现方法如下。
首先需要重写getViewTypeCount与getItemViewType这两个方法,type的值必须从0开始。
private static final int TYPE_1 = 0;
private static final int TYPE_2 = 1;
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
if (position % 5 < 2) {
return TYPE_1;
} else {
return TYPE_2;
}
}
然后就在getView中进行当前位置的判断确定是哪种类型并进行相应的加载。并提供两个ViewHolder进行不同布局的视图控制。当convertView为null时判断一次,convertView与holder绑定时判断一次,以及convertView不为null被复用时判断一次。
getView的相关代码如下:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder1 holder1 = null;
ViewHolder2 holder2 = null;
int type = getItemViewType(position);
if (convertView == null) {
switch (type) {
case TYPE_1:
convertView = LayoutInflater.from(context).inflate(R.layout.list_item1,null);
holder1 = new ViewHolder1();
holder1.tvName = (TextView) convertView.findViewById(R.id.tv_name);
holder1.tvHabit = (TextView) convertView.findViewById(R.id.tv_habit);
holder1.tvAge = (TextView) convertView.findViewById(R.id.tv_age);
convertView.setTag(holder1);
break;
case TYPE_2:
convertView = LayoutInflater.from(context).inflate(R.layout.list_item2,null);
holder2 = new ViewHolder2();
holder2.tvName = (TextView) convertView.findViewById(R.id.tv_name);
holder2.tvAge = (TextView) convertView.findViewById(R.id.tv_age);
convertView.setTag(holder2);
break;
}
}else{
switch (type){
case TYPE_1:
holder1 = (ViewHolder1) convertView.getTag();
break;
case TYPE_2:
holder2 = (ViewHolder2) convertView.getTag();
break;
}
}
People p = list.get(position);
switch (type){
case TYPE_1:
holder1.tvName.setText(p.name);
holder1.tvAge.setText(p.age+"");
holder1.tvHabit.setText(p.habit);
break;
case TYPE_2:
holder2.tvName.setText(p.name);
holder2.tvAge.setText(p.age+"");
break;
}
return convertView;
}
供加载的两种布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/activity_horizontal_margin">
<TextView
android:id="@+id/tv_name"
android:text="name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_habit"
android:text="habit"
android:layout_below="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_age"
android:layout_below="@id/tv_habit"
android:text="0"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:layout_alignParentRight="true"
android:layout_alignBaseline="@id/tv_name"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@mipmap/ic_launcher"/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ccc"
android:padding="@dimen/activity_horizontal_margin">
<TextView
android:id="@+id/tv_name"
android:text="name"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_age"
android:layout_below="@id/tv_name"
android:layout_alignParentRight="true"
android:text="0"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:layout_alignBaseline="@id/tv_name"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@mipmap/ic_launcher"/>
</RelativeLayout>
最后实现的结果:
当时出现异常的情况是:当拖动速度较快时会发生,如果慢慢的拖动则不会出现这种异常,如今不能重现这种情况了。不知道是不是当时进行网络请求的原因。希望有人能够告知一下。