在 RecycleView 适配器中实现多种 ViewHolder 类型 [英] Implement multiple ViewHolder types in RecycleView adapter

查看:52
本文介绍了在 RecycleView 适配器中实现多种 ViewHolder 类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能是讨论而不是问题.

实现多种类型的正常方式

如你所知,如果我们想在RecyclerView中实现多种类型,我们应该提供多个CustomViewHolder扩展RecyclerView.ViewHolder.

例如,

class TextViewHolder 扩展 RecyclerView.ViewHolder{文本视图文本视图;}类 ImageViewHolder 扩展 RecyclerView.ViewHolder{图像视图图像视图;}

然后我们必须重写getItemViewType.并且在onCreateViewHolder 中构造TextViewHolderImageViewHolder.

@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {如果(视图类型 == 0){返回新的 ImageViewHolder(mLayoutInflater.inflate(R.layout.item_image, parent, false));} 别的 {返回新的 TextViewHolder(mLayoutInflater.inflate(R.layout.item_text, parent, false));}}

上面的代码是正常的,但还有另一种方式.

另一种方式

我认为只有一个 CustomViewHolder 就足够了.

 class MultipleViewHolder 扩展 RecyclerView.ViewHolder{文本视图文本视图;图像视图图像视图;MultipleViewHolder(查看 itemView,int 类型){如果(类型== 0){textView = (TextView)itemView.findViewById(xx);}别的{imageView = (ImageView)itemView.findViewById(xx);}}}

您在开发工作中使用哪种方式?

解决方案

我个人喜欢 Yigit Boyar 建议的方法在 本次演讲(快进到 31:07).不是从 getItemViewType() 返回一个 constant int,而是直接返回布局 id,它也是一个 int 并且保证是唯一的:

<前><代码>@覆盖公共 int getItemViewType(int position) {开关(位置){案例0:返回 R.layout.first;情况1:返回 R.layout.second;默认:返回 R.layout.third;}}

这将允许您在 onCreateViewHolder() 中有以下实现:

<前><代码>@覆盖public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {LayoutInflater inflater = LayoutInflater.from(parent.getContext());查看视图 = inflater.inflate(viewType, parent, false);MyViewHolder 持有人 = null;开关(视图类型){案例R.layout.first:持有人 = 新的 FirstViewHolder(view);休息;案例R.layout.second:持有人=新的SecondViewHolder(视图);休息;案例R.layout.third:持有人=新的ThirdViewHolder(视图);休息;}退货持有人;}

其中 MyViewHolder 是一个抽象类:

<前><代码>公共静态抽象类 MyViewHolder 扩展 RecyclerView.ViewHolder {公共 MyViewHolder(查看 itemView){超级(项目视图);//执行特定于所有查看者的操作,例如//ButterKnife.bind(this, itemView);}抽象无效绑定(项目项目);}

FirstViewHolder 如下:

<前><代码>公共静态类 FirstViewHolder 扩展 MyViewHolder {@绑定视图文本视图标题;公共 FirstViewHolder(查看 itemView){超级(项目视图);}@覆盖无效绑定(项目项目){title.setText(item.getTitle());}}

这将使 onBindViewHolder() 成为单行:

<前><代码>@覆盖public void onBindViewHolder(MyViewHolder holder, int position) {holder.bind(dataList.get(holder.getAdapterPosition()));}

因此,您将每个 ViewHolder 分开,其中 bind(Item) 将负责执行特定于该 ViewHolder 的操作.

It's maybe a discussion not a question.

Normal way to implement multiple types

As you know, if we want to implement multiple types in RecyclerView, we should provide multiple CustomViewHolder extending RecyclerView.ViewHolder.

For exmpale,

class TextViewHolder extends RecyclerView.ViewHolder{
    TextView textView;
}

class ImageViewHolder extends RecyclerView.ViewHolder{
    ImageView imageView;
}

Then we have to override getItemViewType.And in onCreateViewHolder to construct TextViewHolder or ImageViewHolder.

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == 0) {
        return new ImageViewHolder(mLayoutInflater.inflate(R.layout.item_image, parent, false));
    } else {
        return new TextViewHolder(mLayoutInflater.inflate(R.layout.item_text, parent, false));
    }
} 

Above code is normal but there is a another way.

Another way

I think only one CustomViewHolder is enough.

 class MultipleViewHolder extends RecyclerView.ViewHolder{
    TextView textView;
    ImageView imageView;

    MultipleViewHolder(View itemView, int type){
       if(type == 0){
         textView = (TextView)itemView.findViewById(xx);
       }else{
         imageView = (ImageView)itemView.findViewById(xx);
       }
    }
 }

Which way do you use in your developing work?

解决方案

Personally I like approach suggested by Yigit Boyar in this talk (fast forward to 31:07). Instead of returning a constant int from getItemViewType(), return the layout id directly, which is also an int and is guaranteed to be unique:


    @Override
    public int getItemViewType(int position) {
        switch (position) {
            case 0:
                return R.layout.first;
            case 1:
                return R.layout.second;
            default:
                return R.layout.third;
        }
    }

This will allow you to have following implementation in onCreateViewHolder():


    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View view = inflater.inflate(viewType, parent, false);

        MyViewHolder holder = null;
        switch (viewType) {
            case R.layout.first:
                holder = new FirstViewHolder(view);
                break;
            case R.layout.second:
                holder = new SecondViewHolder(view);
                break;
            case R.layout.third:
                holder = new ThirdViewHolder(view);
                break;
        }
        return holder;
    }

Where MyViewHolder is an abstract class:


    public static abstract class MyViewHolder extends RecyclerView.ViewHolder {

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

            // perform action specific to all viewholders, e.g.
            // ButterKnife.bind(this, itemView);
        }

        abstract void bind(Item item);
    }

And FirstViewHolder is following:


    public static class FirstViewHolder extends MyViewHolder {

        @BindView
        TextView title;

        public FirstViewHolder(View itemView) {
            super(itemView);
        }

        @Override
        void bind(Item item) {
            title.setText(item.getTitle());
        }
    }

This will make onBindViewHolder() to be one-liner:


    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.bind(dataList.get(holder.getAdapterPosition()));
    }

Thus, you'd have each ViewHolder separated, where bind(Item) would be responsible to perform actions specific to that ViewHolder only.

这篇关于在 RecycleView 适配器中实现多种 ViewHolder 类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆