多 ViewType 的 BaseAdapter 使用

 BaseAdapter可以说是最常用的Adapter了,尤其是它还支持convertView的复用,使得我们的加载View的效率大大提高,然而在实际使用中,存在这样一种情况,ListView中的Item是多种样式的,这样getView()方法中复用的convertView肯定是不同的,那么针对这种情况,我们如何实现convertView的复用呢。其实Android已经考虑到这种情况了,甚至在第一版的API中就为这种情况提供了解决方案,详见下文。

一、关键方法介绍

1.getViewTypeCount ()

  • 返回值类型:int
  • 返回值:当前BaseAdapter中View类型的总数
  • 参考:API文档

1.getItemViewType (int position)

  • 返回值类型:int
  • 返回值:一个表示View类型的int值。如果多个view可以在getView()方法中被互相转换(converted),那么这些view应该是相同的类型,返回相同的类型值。(注意:类型值应该是0getViewTypeCount()-1之间的一个值,也可以返回常量IGNORE_ITEM_VIEW_TYPE:-1)
  • 参考:API文档

二、代码实现

三个布局文件
list_item_red.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FF0000"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/list_item_red_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="14sp" />

</LinearLayout>

list_item_green.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00FF00"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/list_item_green_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="14sp" />

</LinearLayout>

list_item_blue.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0000FF"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/list_item_blue_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="14sp" />

</LinearLayout>

核心类:MultiTypeBaseAdapter.java

public class MultiTypeBaseAdapter extends BaseAdapter {

    public MultiTypeBaseAdapter(int itemCount) {
        this.itemCount = itemCount;
    }

    @Override
    public int getCount() {
        return itemCount;
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemViewType(int position) {
        switch (position % 3) {
        case 0:
            return RED;
        case 1:
            return GREEN;
        case 2:
            return BLUE;
        default:
            return IGNORE_ITEM_VIEW_TYPE;
        }
    }

    @Override
    public int getViewTypeCount() {
        return TYPECOUNT;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        int type = getItemViewType(position);

        switch (type) {
        case RED:
            final HolderRed holderRed;
            if (convertView == null) {
                holderRed = new HolderRed();
                convertView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.list_item_red, parent, false);
                holderRed.textRed = (TextView) convertView.findViewById(R.id.list_item_red_tv);
                convertView.setTag(holderRed);
            } else {
                holderRed = (HolderRed) convertView.getTag();
            }
            holderRed.textRed.setText(String.valueOf(position));
            break;

        case GREEN:
            final HolderGreen holderGreen;
            if (convertView == null) {
                holderGreen = new HolderGreen();
                convertView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.list_item_green, parent, false);
                holderGreen.textGreen = (TextView) convertView.findViewById(R.id.list_item_green_tv);
                convertView.setTag(holderGreen);
            } else {
                holderGreen = (HolderGreen) convertView.getTag();
            }
            holderGreen.textGreen.setVisibility(View.INVISIBLE);
            break;

        case BLUE:
            final HolderBlue holderBlue;
            if (convertView == null) {
                holderBlue = new HolderBlue();
                convertView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.list_item_blue, parent, false);
                holderBlue.textBlue = (TextView) convertView.findViewById(R.id.list_item_blue_tv);
                convertView.setTag(holderBlue);
            } else {
                holderBlue = (HolderBlue) convertView.getTag();
            }
            holderBlue.textBlue.setVisibility(View.GONE);
            break;
        }

        return convertView;
    }

    private int itemCount;
    private static final int TYPECOUNT = 3;// 类型总数
    // 三种类型,对应类型值应为0至TYPECOUNT-1
    private static final int RED = 0;
    private static final int GREEN = 1;
    private static final int BLUE = 2;

    private final class HolderRed {
        TextView textRed;
    }

    private final class HolderGreen {
        TextView textGreen;
    }

    private final class HolderBlue {
        TextView textBlue;
    }
}

三、效果图

效果图