android之实现万能适配RecyclerView的adapter

本文介绍如何创建一个万能的RecyclerView Adapter,避免重复编写Adapter。内容包括自定义ViewHolder,使用接口处理不同布局的控件初始化和数据绑定,以及添加header、下拉刷新和上拉加载更多的功能。适配器的实现思路借鉴了鸿洋大神的方法。
摘要由CSDN通过智能技术生成

现在基本大家都推荐RecyclerView,很少有人使用ListView了,包括我自己也是,已经很久没用ListView了,所以关于ListView的万能adapter就不写了。
每次写项目的时候,每次遇到RecyclerView都要重新写一个Adapter,一大堆东西重复写,麻烦死了,实在是忍不住了,以前懒,总是懒得去搞快捷的adapter,现在项目里面好多个RecyclerView,马丹,写adapter写吐,所以麻溜麻溜的来写个万能adapter了,这种东西网上很多,原理差不多都是重写ViewHolder和Adapter,主要是使用泛型实现。废话不多说,撸代码吧。

注意:我的万能adapter中集成了下拉刷新、上拉加载更多、另增header的功能,需要与我后面将写到的万能下拉刷新、上拉加载更多的RecyclerView搭配使用,如果你不需要下拉刷新和上拉加载更多可以无视其中相关的代码。

首先,我们知道我们对adapter中控件获取都是通过ViewHolder来的,所以我们首先要自定义ViewHolder,来完成各个控件的获取和初始化。正常情况下,我们是这样用的:

class HistoryGoodsHolder extends RecyclerView.ViewHolder {
        ImageView img;
        TextView name, summary, amount, price;

        public HistoryGoodsHolder(View itemView) {
            super(itemView);
            img = (ImageView) itemView.findViewById(R.id.item_history_rcv_goodsImg);
            name = (TextView) itemView.findViewById(R.id.item_history_rcv_goodsName);
            summary = (TextView) itemView.findViewById(R.id.item_history_rcv_goodsSummary);
            amount = (TextView) itemView.findViewById(R.id.item_history_rcv_goodsAmount);
            price = (TextView) itemView.findViewById(R.id.item_history_rcv_goodsPrice);
        }
    }

现在我们需要实现的是万能的adapter,所以holder必须实现可定制化,而不是这种固定死的,每个RecyclerView的item布局不一样就重新写个holder,这样就没有意义了,所以我们写的万能Holder中不能存在真实的控件id,因为一旦id固定,那么肯定得重复写holder,毕竟id不一样,holder就不一样了,所以我们可以通过一种方式,那就是findById方法里面的id不写死,而是用参数的方式传进去,这样可以写一个通用的Holer,不同的recyclerview可以传不同的id进去就行了。ViewHolder最终形态:

public class XJJBaseRvHolder extends RecyclerView.ViewHolder {
   
    private SparseArray<View> mViews;  //view的集合
    private View mConvertView;  //item的布局
    private Context mContext;  //上下文

    public XJJBaseRvHolder(Context context, View itemView) {
        super(itemView);
        mContext = context;
        mConvertView = itemView;
        mViews = new SparseArray<View>();
    }

    //获取item的布局
    public View getItemView(){
        return mConvertView;
    }

    //初始化控件,通过传进去id来初始化,使用泛型实现传递任何类型
    public <T extends View> T getView(int viewId)
    {
        View view = mViews.get(viewId);
        if (view == null)
        {
            view = mConvertView.findViewById(viewId);
            mViews.put(viewId, view);
        }
        return (T) view;
    }

    //快捷设置TextView的文本
    public XJJBaseRvHolder setText(int viewId, String text)
    {
        TextView tv = getView(viewId);
        tv.setText(text);
        return this;
    }

    //快捷设置ImageView的图片
    public XJJBaseRvHolder setSrc(int viewId, int resId)
    {
        ImageView view = getView(viewId);
        view.setImageResource(resId);
        return this;
    }

    //设置控件的点击事件
    public XJJBaseRvHolder setOnClickListener(int viewId, View.OnClickListener listener)
    {
        View view = getView(viewId);
        view.setOnClickListener(listener);
        return this;
    }

    //设置item的点击事件
    public XJJBaseRvHolder setItemOnClickListener(View.OnClickListener listener){
        mConvertView.setOnClickListener(listener);
        return this;
    }

ViewHolder搞定,接下来是adapter,ViewHolder是在adapter里面被引用的,如果我们在adapter里面实例化holder后传入id来初始化控件,肯定不行,因为如果在adapter里面传入id,那么adapter使用了真实的id,那么id不一样adapter又得不一样,还得重复写了,所以我们不能在adapter里面传入id来初始化item的控件,那么怎么实现呢?用接口来实现,具体如下:
先写接口把Holder传递出去,然后初始化adapter的时候实现改接口。

public interface ItemDataListener<T> {
  //接口
        void setItemData(XJJBaseRvHolder holder, T t);
    }

public void setItemDataListener(ItemDataListener listener) {
        itemDataListener = listener;
    }

然后我们数据填充的时候需要先初始化控件的,所以我在onBindViewHolder里面调用接口࿰

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值