1. 程式人生 > >ListView的Adapter有多個ViewHolder的時候導致的ViewHolder型別轉換錯誤!

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一下,免得忘記了,後頭再補充。