如何使用3种不同的视图类型处理getItemViewType

时间:2017-09-09 12:09:45

标签: java android android-recyclerview android-adapter android-viewholder

基本上,我有一个Recyclerview应该填充来自服务器的数据,有3种类型的项目(照片,视频,论文)我正确地做了一切并且它正常显示但是一旦我开始滚动它就崩溃了这个错误:< / p>

   java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2

数组不为空,photo = 2,videos = 1和essay = 1的数组大小。 我确定错误是由getItemViewType方法引起的,我真的无法理解它背后的原因,我已经阅读了一些关于它的角色的定义,但仍然可以处理这个时间!

我只想将所有数组中的所有项目按顺序放在一个回收站中!

适配器:

public class GalleryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

  final int VIEW_TYPE_PHOTO = 0;
  final int VIEW_TYPE_VIDEO = 1;
  final int VIEW_TYPE_ESSAY = 2;

  public GalleryAdapter(ArrayList<Gallery.Photo> photo, ArrayList<Gallery.Vedio> video,
      ArrayList<Gallery.Essay> essay, Context context) {
    this.photo = photo;
    this.video = video;
    this.essay = essay;
    this.context = context;
  }

  ArrayList<Gallery.Photo> photo;
  ArrayList<Gallery.Vedio> video;
  ArrayList<Gallery.Essay> essay;
  Context context;


  @Override
  public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    // for photos and videos
    View itemLayoutView1 = LayoutInflater.from(parent.getContext()).inflate(
        R.layout.gallery_item1, parent, false);

   // for essay
    View itemLayoutView2 = LayoutInflater.from(parent.getContext()).inflate(
        R.layout.gallery_item2, parent, false);

    switch (viewType) {

      case VIEW_TYPE_PHOTO:

        PhotoViewHolder photoholder = new PhotoViewHolder(itemLayoutView1);
        return photoholder;

      case VIEW_TYPE_VIDEO:

        VideoViewHolder videoholder = new VideoViewHolder(itemLayoutView1);
        return videoholder;

      case VIEW_TYPE_ESSAY:

        EssayViewHolder essayholder = new EssayViewHolder(itemLayoutView2);
        return essayholder;

      default:
        return null;
    }


  }

  public int getViewTypeCount() {
    return 3;
  }

  @Override
  public int getItemViewType(int position) {

    // return 0; // I tried this line only and still caused the same crash

   // causes the same crash
    switch (position) {
      case 0:
        return VIEW_TYPE_PHOTO;
      case 1:
        return VIEW_TYPE_VIDEO;
      case 2:
        return VIEW_TYPE_ESSAY;
      default:
        return -1;
      }
  }


  @Override
  public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {


    if (holder instanceof PhotoViewHolder) {
      ((PhotoViewHolder) holder).pupulatePhoto(photo.get(position));
    }

     if (holder instanceof VideoViewHolder) {
      ((VideoViewHolder) holder).pupulateVideo(video.get(position));
    }

    if (holder instanceof EssayViewHolder) {
      ((EssayViewHolder) holder).pupulateEssay(essay.get(position));
    }


  @Override
  public int getItemCount() {
    return photo.size() + video.size() + essay.size();
  }

  public class PhotoViewHolder extends RecyclerView.ViewHolder {

    private TextView title;
    private TextView counter;
    private TextView dummy;
    private ImageView itemPic;
    private ImageView eassyCover;

    public PhotoViewHolder(View itemView) {
      super(itemView);

      title = (TextView) itemView.findViewById(R.id.title);
      counter = (TextView) itemView.findViewById(R.id.counter);
      dummy = (TextView) itemView.findViewById(R.id.dummy_txt);
      itemPic = (ImageView) itemView.findViewById(R.id.item_pic);
      eassyCover = (ImageView) itemView.findViewById(R.id.essay_cover);
    }


    public void pupulatePhoto(Gallery.Photo photo) {
      title.setText("Photo " + photo.getTitle());
      Picasso.with(context).load(photo.getImage()).placeholder(R.drawable.bg_blur).into(itemPic);
    }
  }

  public class VideoViewHolder extends RecyclerView.ViewHolder {


    private TextView title;
    private TextView counter;
    private TextView dummy;
    private ImageView itemPic;
    private ImageView eassyCover;

    public VideoViewHolder(View itemView) {
      super(itemView);

      title = (TextView) itemView.findViewById(R.id.title);
      counter = (TextView) itemView.findViewById(R.id.counter);
      dummy = (TextView) itemView.findViewById(R.id.dummy_txt);
      itemPic = (ImageView) itemView.findViewById(R.id.item_pic);
      eassyCover = (ImageView) itemView.findViewById(R.id.essay_cover);
    }

    public void pupulateVideo(Gallery.Vedio video) {
      title.setText("Video " + video.getTitle());
      Picasso.with(context).load(video.getPreviewImage()).placeholder(R.drawable.bg_blur)
          .into(itemPic);
    }

  }

  public class EssayViewHolder extends RecyclerView.ViewHolder {


    private TextView title;
    private TextView counter;
    private TextView dummy;
    private ImageView itemPic;
    private ImageView eassyCover;

    public EssayViewHolder(View itemView) {
      super(itemView);

      title = (TextView) itemView.findViewById(R.id.title);
      counter = (TextView) itemView.findViewById(R.id.counter);
      dummy = (TextView) itemView.findViewById(R.id.dummy_txt);
      itemPic = (ImageView) itemView.findViewById(R.id.item_pic);
      eassyCover = (ImageView) itemView.findViewById(R.id.essay_cover);
    }

    public void pupulateEssay(Gallery.Essay essay) {
      title.setText("Essay " + essay.getTitle());
    }
  }

}

更新#1

当我尝试将所有三个组合在一起时适配器的新代码:

public class GalleryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

  final int VIEW_TYPE_PHOTO = 0;
  final int VIEW_TYPE_VIDEO = 1;
  final int VIEW_TYPE_ESSAY = 2;

  ArrayList<Object> objects;
  Context context;

  public GalleryAdapter(ArrayList<Object> objects, Context context) {
    this.objects = objects;
    this.context = context;
  }

  @Override
  public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext())
        .inflate(R.layout.gallery_item2, parent, false);

    switch (viewType) {

      case VIEW_TYPE_PHOTO:
        PhotoViewHolder photoholder = new PhotoViewHolder(view);
        return photoholder;

      case VIEW_TYPE_VIDEO:
        VideoViewHolder videoholder = new VideoViewHolder(view);
        return videoholder;

      case VIEW_TYPE_ESSAY:
        view = LayoutInflater.from(parent.getContext()).inflate(
            R.layout.gallery_item, parent, false);

        EssayViewHolder essayholder = new EssayViewHolder(view);
        return essayholder;

      default:
        return null;
    }

  }

  @Override
  public int getItemViewType(int position) {

//Gallery.Photo and Gallery.Vedio are the models
    if (objects.get(position) instanceof Gallery.Photo) {
      return VIEW_TYPE_PHOTO;
    } else if (objects.get(position) instanceof Gallery.Vedio) {
      return VIEW_TYPE_VIDEO;
    } else {
      return VIEW_TYPE_ESSAY;
    }
  }

  @Override
  public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {

    if (getItemViewType(position) == VIEW_TYPE_PHOTO) {


          // gives me NPE !
//      ((PhotoViewHolder) holder).pupulatePhoto(objects.get(position));


    } else if (getItemViewType(position) == VIEW_TYPE_VIDEO) {


    } else {


    }


  @Override
  public int getItemCount() {
    return objects.size();
  }

  public class PhotoViewHolder extends RecyclerView.ViewHolder {


    private TextView title;
    private TextView counter;
    private TextView dummy;
    private ImageView itemPic;
    private ImageView eassyCover;

    public PhotoViewHolder(View itemView) {
      super(itemView);

      title = (TextView) itemView.findViewById(R.id.title);
      counter = (TextView) itemView.findViewById(R.id.counter);
      dummy = (TextView) itemView.findViewById(R.id.dummy_txt);
      itemPic = (ImageView) itemView.findViewById(R.id.item_pic);
      eassyCover = (ImageView) itemView.findViewById(R.id.essay_cover);
    }

    public void pupulatePhoto(Gallery.Photo photo) {
      title.setText("Photo " + photo.getTitle());
Picasso.with(context).load(photo.getImage()).placeholder(R.drawable.bg_blur).into(itemPic);
    }
  }

  public class VideoViewHolder extends RecyclerView.ViewHolder {


    private TextView title;
    private TextView counter;
    private TextView dummy;
    private ImageView itemPic;
    private ImageView eassyCover;

    public VideoViewHolder(View itemView) {
      super(itemView);

      title = (TextView) itemView.findViewById(R.id.title);
      counter = (TextView) itemView.findViewById(R.id.counter);
      dummy = (TextView) itemView.findViewById(R.id.dummy_txt);
      itemPic = (ImageView) itemView.findViewById(R.id.item_pic);
      eassyCover = (ImageView) itemView.findViewById(R.id.essay_cover);
    }

    public void pupulateVideo(Gallery.Vedio video) {

      title.setText("Video " + video.getTitle());   Picasso.with(context).load(video.getPreviewImage()).placeholder(R.drawable.bg_blur)
          .into(itemPic);
    }

  }

  public class EssayViewHolder extends RecyclerView.ViewHolder {


    private TextView title;
    private TextView counter;
    private TextView dummy;
    private ImageView itemPic;
    private ImageView eassyCover;

    public EssayViewHolder(View itemView) {
      super(itemView);

      title = (TextView) itemView.findViewById(R.id.title);
      counter = (TextView) itemView.findViewById(R.id.counter);
      dummy = (TextView) itemView.findViewById(R.id.dummy_txt);
      itemPic = (ImageView) itemView.findViewById(R.id.item_pic);
      eassyCover = (ImageView) itemView.findViewById(R.id.essay_cover);
    }

    public void pupulateEssay(Gallery.Essay essay) {
      title.setText("Essay " + essay.getTitle());
    }
  }


}

效果很好,但我无法正确获取物品的位置?当我调用此方法来填充数据并将其与视图绑定时...它会崩溃并给我NPE?

   ((PhotoViewHolder) holder).pupulatePhoto(objects.get(position));

但它给了我一个NPE!每次我使用它的位置都会崩溃。我错过了什么!?

更新#2

我解决了它,我忘了施放模型arraylist'_'所以我改变了这个

   ((PhotoViewHolder) holder).pupulatePhoto(objects.get(position));

到这个

    ((PhotoViewHolder) holder).pupulatePhoto( (Gallery.Photo) objects.get(position));

现在可行:D

非常感谢。!

1 个答案:

答案 0 :(得分:0)

我的解决方案是将所有三个数组列表组合成一个来自Object类型并使用适配器构造函数实例化,然后使用instanceof和相应的模型检查当前位置。

@Override
  public int getItemViewType(int position) {

//Gallery.Photo and Gallery.Vedio are the models
    if (objects.get(position) instanceof Gallery.Photo) {
      return VIEW_TYPE_PHOTO;
    } else if (objects.get(position) instanceof Gallery.Vedio) {
      return VIEW_TYPE_VIDEO;
    } else {
      return VIEW_TYPE_ESSAY;
    }
  }

有关详细信息,请参阅更新#1和#2。