封装RecyclerView Adapter 实现可添加多个header和footer,可设置loadingView,低耦合的多种布局。

开篇先放代码:戳我下载代码

多种布局的recyclerview的普通写法是重写RecyclerView.Adapter的getItemViewType返回不同position上的type,在onCreateViewHolder(ViewGroup parent,int viewType)里根据不同的type创建不同的viewholder,之后在onBindViewHolder(RecyclerView.ViewHolder holder, int position)里根据不同的viewholder进行数据绑定。但是这种写法具有高度耦合性,每添加一种布局都要在adapter的三个方法做修改。
改进方法
首先封装一个BaseViewHolder:

public abstract class BaseViewHolder<T> extends RecyclerView.ViewHolder {

    View mItemView;
    //缓存View
    SparseArray<View> mViews;

    public BaseViewHolder(View itemView) {
        super(itemView);
        mItemView = itemView;
        mViews = new SparseArray<>();
    }

    public View getView(int resId) {
        View view = mViews.get(resId);
        if (view == null) {
            view = mItemView.findViewById(resId);
            mViews.put(resId, view);
        }
        return view;
    }

    public void setVisibility(int resId, boolean visible) {
        View view = getView(resId);
        if (view != null) {
            view.setVisibility(visible ? View.VISIBLE : View.GONE);
        }
    }

    public abstract void bindData(T data);
}

使用SparseArray缓存View,避免每次都调用findViewById。
然后创建一个接口,里面包含根据不同bean返回不同type类型的方法,和创建ViewHolder的方法:

public interface TypeFactory {
    BaseViewHolder createViewHolder(int type, View itemView);
    int type(ChannelEntity channelEntity);
    int type(EntityTwo entityTwo);
}

然后创建TypeFactory的实现类实现上述方法,其中type方法返回对应的布局id,因为id不可重复,这样就可以利用id值作为不同布局类型的type值:

public class ItemTypeFactory implements TypeFactory{
    @Override
    public BaseViewHolder createViewHolder(int type, View itemView) {
        switch (type){
            case R.layout.item_my:
                return new ViewHolderOne(itemView);
            case R.layout.item_other:
                return new ViewHolderTwo(itemView);
        }
        return null;
    }

    @Override
    public int type(ChannelEntity channelEntity) {
        return R.layout.item_my;
    }

    @Override
    public int type(EntityTwo entityTwo) {
        return R.layout.item_other;
    }
}

接下来创建实体bean类的抽象基类,包含一个抽象方法

public abstract class BaseModel {
    public abstract int type(TypeFactory typeFactory) ;
}

创建不同的实体类

public class ChannelEntity extends BaseModel {
    int id;
    String name;
    String letter;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLetter() {
        return letter;
    }

    public void setLetter(String letter) {
        this.letter = letter;
    }

    @Override
    public int type(TypeFactory typeFactory) {
        return typeFactory.type(this);
    }
}

最后是BaseRecyclerAdapter,里面包含一个ItemTypeFactory实例,然后在getItemViewType(int position)返回mData.get(getRealPosition(position)).type(itemTypeFactory);将不同布局文件id作为type返回:

@Override
    public int getItemViewType(int position) {

                return mData.get(getRealPosition(position)).type(itemTypeFactory);
    }

在onCreateViewHolder(ViewGroup parent, int viewType)里根据getItemViewType方法里返回的不同的布局id来创建对应的ViewHolder

 @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                return itemTypeFactory.createViewHolder(viewType, view);
        }

    }

最后在onBindViewHolder方法里调用baseviewholder的bindData方法绑定数据。
此外我还在BaseRecyclerAdapter里实现了添加头尾布局及列表底部的loading布局的方法,以及在更新数据时利用DiffUtil对新旧数据集比较,防止调用notifyDataSetChanged来更新整个recyclerView。具体请看我的github上的代码:
戳我下载代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值