RecyclerView.Adapter再次封装

RecyclerView.Adapter相比ListView的Adapter的写法已经相当简洁。但是在使用中实现的方法还是有点多,所以,在借鉴其他大神的写法中,总结一下自认为比较简便RecyclerView.Adapter写法。

0x00:RecyclerView.Adapter 原来的写法

RecyclerView.Adapter常规实现方法相比ListView已经相当精简
实现三个接口,再继承一个RecyclerView.ViewHolder就完成
以下是TestAdapter实现RecyclerView.Adapter的范例

/**
 * @author Rock you
 */
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyViewHolder>{

    private List<String> mDataList;

    private Context mContext;

    public TestAdapter(Context context, List<String> dataList) {
            this.mContext = context;
            this.mDataList = dataList;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(mContext);
        View view = layoutInflater.inflate(R.layout.test_item, parent, false);
        MyViewHolder myViewHolder = new MyViewHolder(view);
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        Button button = holder.mButton;
        button.setText(mDataList.get(position));
    }

    @Override
    public int getItemCount() {
        if (mDataList == null){
            return 0;
        }
        return mDataList.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder{

        Button mButton;

        public MyViewHolder(View itemView) {
            super(itemView);
            mButton = (Button)itemView.findViewById(R.id.main_item_btn);
        }
    }
}

如上所述,在写大项目的时候,如果存在有许多Adapter,必然是一个很大的工程量。
所以,为了简化Adapter,所需要实现的接口越少越好。

0x01:RecyclerView.Adapter简化

废话不多说直接上代码

/**
 * RecyclerView.Adapter的再封装
 * 只需要复写两个abstract方法即可
 * Created by Rock you
 */
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<BaseRecyclerAdapter.BaseViewHolder>{

    private Context mContext;

    private LayoutInflater mLayoutInflater;

    //数据源
    protected List<T> mListData;

    private BaseRecyclerAdapter.OnItemClickListener mItemClickListener;

    /**
     * 构造函数
     * @param context
     */
    public BaseRecyclerAdapter(Context context){
        this(context, Collections.<T>emptyList());
    }

    /**
     * 构造函数
     * @param context
     * @param listData
     */
    public BaseRecyclerAdapter(Context context, List<T> listData){
        this.mListData = listData;
        this.mContext = context;
        this.mLayoutInflater = LayoutInflater.from(context);
    }

    /**
     * 设置数据源
     * @param listData
     */
    public void setListData(List<T> listData){
        this.mListData = listData;
    }

    public void setItemClickListener(BaseRecyclerAdapter.OnItemClickListener itemClickListener){
        this.mItemClickListener = itemClickListener;
    }

    /**
     * 复写来自RecyclerView.Adapter的
     * onCreateViewHolder抽象方法
     * @param parent
     * @param viewType
     * @return
     */
    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = mLayoutInflater.inflate(getLayoutID(), parent, false);
        BaseViewHolder viewHolder = new BaseViewHolder(view);
        return viewHolder;
    }

    /**
     * 复写来自RecyclerView.Adapter的
     * onBindViewHolder抽象方法
     * @param holder
     * @param position
     */
    @Override
    public void onBindViewHolder(BaseViewHolder holder, int position) {
        holder.setItemClickListener(mItemClickListener, position);
        bindHolder(holder, position);
    }

    /**
     * 复写来自RecyclerView.Adapter的
     * getItemCount的抽象方法
     * @return
     */
    @Override
    public int getItemCount() {
        if (mListData == null){
            return 0;
        }
        return mListData.size();
    }

    /**
     * 返回该itemView的id值
     * @return itemView的id
     */
    protected abstract int getLayoutID();

    /**
     * 绑定ViewHolder
     * 通过调用holder的getItemView得到任何View
     * 或者getImageView得到ImageView
     * getTextView得到TextView
     * getEditText得到EditText
     * 同时在做上述getxxx操作的过程中通过id find各个View
     * @param holder
     * @param position
     */
    protected abstract void bindHolder(BaseViewHolder holder, int position);

    /**
     * BaseViewHolder类
     * 静态类,防止持有外部类的引用,造成内存泄露
     * 在bindHolder中调用BaseViewHolder的
     * getItemView和getImageView,getTextView,getEditText
     */
    static class BaseViewHolder extends RecyclerView.ViewHolder {

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

        public void setItemClickListener(
            final BaseRecyclerAdapter.OnItemClickListener listener, 
            final int position){
                itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (listener != null){
                            listener.onItemClick(itemView, position);
                        }
                    }
                });
            }

        /**
         * 重要代码
         * 利用定义在方法上的泛型
         * 方法返回什么类型的View,就绑定什么类型的View
         * @param id
         * @param <T>
         * @return
         */
        public <T extends View> T getItemView(int id){
            T v = (T)itemView.findViewById(id);
            if (v == null){
                throw new IllegalArgumentException("itemView's id no exist or error!");
            }
            return v;
        }

        public ImageView getImageView(int id){
            return getItemView(id);
        }

        public TextView getTextView(int id){
            return getItemView(id);
        }

        public EditText getEditText(int id){
            return getItemView(id);
        }
    }

    /**
     * 整个ItemView的回调接口
     */
    public interface OnItemClickListener{
        void onItemClick(View itemView, int position);
    }
}

我将原先的三个接口(‘onCreateViewHolder‘,’onBindViewHolder‘,’getItemCount‘)实现,对外提供’getLayoutID‘和’bindHolder‘接口。由于RecyclerView的没有提供itemView的回调接口,所以在Adapter内部提供一个接口

    /**
     * 整个ItemView的回调接口
     */
    public interface OnItemClickListener{
        void onItemClick(View itemView, int position);
    }

0x02:BaseRecyclerAdapter的使用

实现BaseRecyclerAdapter实现后的代码只需要实现”getLayoutID“和”bindHolder“即可。
“getLayoutID”返回该RecyclerView的layoutID,”bindHolder”中处理逻辑和绑定View。
View的绑定一句话就可以搞定”Button button = holder.getItemView(R.id.my_id);”,是不是相当简洁。
使用方法:

/**
 * Created by Rock You
 */
public class MainAdapter extends BaseRecyclerAdapter<String>{


    public MainAdapter(Context context, List<String> listData) {
        super(context, listData);
    }

    // 该Adapter的layout资源
    @Override
    protected int getLayoutID() {
        return R.layout.main_item;
    }

    // 绑定数据
    @Override
    protected void bindHolder(BaseViewHolder holder, int position) {
        Button button = holder.getItemView(R.id.main_item_btn);
        String text = mListData.get(position);
        if (!TextUtils.isEmpty(text)){
            button.setText(text);
        }
    }
}

你肯定会纳闷绑定数据是怎么做的?
数据绑定利用java泛型知识来实现,如下代码

public <T extends View> T getItemView(int id){
    T v = (T)itemView.findViewById(id);
    if (v == null){
       throw new IllegalArgumentException("itemView's id no exist or error!");
    }
    return v;
}

public ImageView getImageView(int id){
    return getItemView(id);
}

public TextView getTextView(int id){
    return getItemView(id);
}

public EditText getEditText(int id){
    return getItemView(id);
}

利用定义在方法上的泛型。
实际上就是,返回值是什么类型,就绑定什么类型。比如返回Button,就绑定Button类型

Button button = holder.getItemView(R.id.main_item_btn);

这样写法有效避免每次写Adapter都需要”findViewById”。达到简化的目的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rockyou666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值