ListView的Adapter有多个ViewHolder的时候导致的ViewHolder类型转换错误!

问题复现

背景是这样的,我用的CursorAdapter,然后重写了getViewTypeCount方法

  @Override
    public int getViewTypeCount() {
        return TYPE_COUNT;
    }
 我又自己实现了一个getItemViewType方法

   public int getItemViewType(Cursor cursor) {
        。。。省略
        if (leadUserId == fromUserId) {
            return TYPE_RECEIVE;
        } else {// if (leadUserId == toUserId)
            return TYPE_SEND;
        }

    }

我的getView是正常写法,因为牵涉到公司项目,就不贴了,但是写法类似下面的代码:

package com.org.mmp.Play;

import java.util.List;

import com.org.mmp.R;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class PlayAdapter extends BaseAdapter {
  /**
   * 标题的item
   */
  public static final int ITEM_TITLE = 0;
  /**
   * 二级菜单的item
   */
  public static final int ITEM_INTRODUCE = 1;
  private List<ViewItem> mList;
  private Context context;

  private LayoutInflater inflater;

  // 两个样式 两个holder。100就写100holder。。当然你何以把他抽离出来这里先只为了说明问题
  class Holder1 {
    TextView play_title;

    Holder1(View view) {
      play_title = (TextView) view.findViewById(R.id.play_title);
    }

  }

  class Holder2 {
    TextView play_introduce_title;
    ImageView play_iv;

    Holder2(View view) {
      play_introduce_title = (TextView) view
          .findViewById(R.id.play_introduce_title);
      play_iv = (ImageView) view.findViewById(R.id.play_iv);
    }
  }

  public PlayAdapter(Context context, List<ViewItem> mList) {
    this.context = context;
    this.mList = mList;
    inflater = LayoutInflater.from(context);
  }

  @Override
  public int getCount() {
    // TODO Auto-generated method stub
    System.out.println("mList.size()" + mList.size());
    return mList.size();
  }

  @Override
  public Object getItem(int arg0) {
    // TODO Auto-generated method stub
    return mList.get(arg0);
  }
  //返回 代表某一个样式 的 数值  
  @Override
  public int getItemViewType(int position) {
    // TODO Auto-generated method stub
    return mList.get(position).type;
  }

  //两个样式 返回2
  @Override
  public int getViewTypeCount() {
    // TODO Auto-generated method stub
    return 2;
  }

  @Override
  public long getItemId(int arg0) {
    // TODO Auto-generated method stub
    return arg0;
  }

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

    Holder1 holder1 = null;
    Holder2 holder2 = null;
    System.out.println("getView " + position + " " + convertView
        + " type = " + type);
    if (convertView == null) {
      //选择某一个样式。。
      switch (type) {
      case ITEM_TITLE:
        convertView = inflater.inflate(R.layout.play_item_title, null);
        holder1 = new Holder1(convertView);

        holder1.play_title.setText(mList.get(position).name);

        convertView.setTag(holder1);
        break;
      case ITEM_INTRODUCE:
        convertView = inflater.inflate(R.layout.paly_item_introduce,
            null);
        holder2 = new Holder2(convertView);

        holder2.play_introduce_title
            .setText(mList.get(position).address);
        convertView.setTag(holder2);
        break;
      default:
        break;
      }
    } else {
      switch (type) {
      case ITEM_TITLE:
        holder1 = (Holder1) convertView.getTag();
        holder1.play_title.setText(mList.get(position).name);
        break;
      case ITEM_INTRODUCE:
        holder2 = (Holder2) convertView.getTag();
        holder2.play_introduce_title
            .setText(mList.get(position).address);
        break;

      default:
        break;
      }

    }

    return convertView;
  }

}
结果一直给我报错,说ViewHolder1不能强制被转换为ViewHolder2....


解决方案:

1.一个致命的错误,我们应该重写getItemViewType(int position)方法,而不是自己写一个,因为这个方法的返回值在ListView的源码中会用,主要是跟它的复用有关系吧,我猜测。具体的原因需要花时间研究一下,今天先mark一下,免得忘记了,后头再补充。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值