为RecyclerView打造简单易用扩展性高的万能适配器

相信用listview开发的过程当中我们肯定用过各类万能的Adapter适配器,当我们迁移到使用Recycleview的开发中会发现虽然它的功能比listview强大不少,但是代码写起来还是略显麻烦了些,于是我们感觉也要使用一个简单易用的万能适配器来写代码,前段时候受到了一篇博客的启发,感觉实现的还是不够简洁和扩展性强,于是想到了一种封装方式,写一个万能适配器,让大家使用。
下面我们直奔主题讲解一下思路,首先我们想到的是把Adapter和viewholder分离开两个类来实现,这样做的好处是降低了代码的耦合,思路更加的清晰:

public abstract class BaseRecyclerAdapter<T>  extends RecyclerView.Adapter<RecyclerHolder> {

    protected List<T> dataSources;
    protected Context mContext;
    protected final int mItemLayoutId;
    private OnItemClickListener listener;
    private OnItemLongClickListener longlistener;

    public BaseRecyclerAdapter(RecyclerView v, Collection<T> datas, int itemLayoutId) {
        if (datas == null) {
            dataSources = new ArrayList<>();
        } else if (datas instanceof List) {
            dataSources = (List<T>) datas;
        } else {
            dataSources = new ArrayList<>(datas);
        }
        this.mContext=v.getContext();
        this.mItemLayoutId=itemLayoutId;
    }

    @Override
    public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Log.e("测试","onCreateViewHolder");
        View root = LayoutInflater.from(mContext).inflate(mItemLayoutId, parent, false);
        return new RecyclerHolder(root);
    }

    @Override
    public void onBindViewHolder(RecyclerHolder holder, int position) {
        Log.e("测试","onBindViewHolder"+position);
        convert(holder, dataSources.get(position), position);
        holder.itemView.setOnClickListener(getitemviewOnClickListener(position));
        holder.itemView.setOnLongClickListener(getitemviewOnLongClickListener(position));
    }

    /**
     * 让子类实现的抽象方法
     * @param holder  holder
     * @param item    一般是实体bean对象
     * @param position  item的位置
     */
    public abstract void convert(RecyclerHolder holder, T item, int position);

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

    public View.OnClickListener getitemviewOnClickListener(final int position) {
        return new View.OnClickListener() {
            @Override
            public void onClick(@Nullable View v) {
                if (listener != null && v != null) {
                    listener.onItemClick(v, dataSources.get(position), position);//回调
                }
            }
        };
    }
    public View.OnLongClickListener getitemviewOnLongClickListener(final int position) {
        return new View.OnLongClickListener(){
            @Override
            public boolean onLongClick(View v) {
                if (listener != null && v != null) {
                    longlistener.onItemLongClick(v, dataSources.get(position), position);//回调
                }
                return true;
            }
        };
    }

    //--------------类似的方法根据自己需求自己添加-------------------------------------
    public interface OnItemClickListener {
        void onItemClick(View view, Object data, int position);
    }
    public void setOnItemClickListener(OnItemClickListener listener) {
        this.listener = listener;
    }
    public interface OnItemLongClickListener {
        void onItemLongClick(View view, Object data, int position);
    }
    public void setOnItemLongClickListener(OnItemLongClickListener longlistener) {
        this.longlistener = longlistener;
    }
}

在构造方法当中我传入了recycleview对象,集合对象以及布局的id,通过recycleview对象我们可以获得上下文对象,为什么这里不是直接传入context对象呢,因为这样做的目的是增加适配器的扩展性,通过这个recycleview对象我们还可以添加很多有用的方法,比如说调用addOnScrollListener方法可以获取recycleveiw滑动的距离,这个时候你可以在下面继续添加接口回调来实现自己的需要等等,传入布局的id更方便了我们只需关注赋值操作就可以。

public class RecyclerHolder extends RecyclerView.ViewHolder {
    private SparseArray<View> mViews;//集合类,以view的id作为key,value是view对象(SparseArray比HashMap更省内存,只能存储key为int类型的数据)
    public RecyclerHolder(View itemView) {
        super(itemView);
        this.mViews=new SparseArray<View>();
    }

    /**
     * 这种写法代替用findViewById的写法来保存引用在holder对象当中,用SparseArray集合来保存对象引用
     * @param viewId  控件的id
     * @param <T>
     * @return
     */
    public <T extends View> T getView(int viewId) {
        View view = mViews.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);//itemView在构造方法传进去了
            mViews.put(viewId, view);
        }
        return (T) view;
    }
    /**
     * 为TextView设置字符串
     *
     * @param viewId
     * @param text
     * @return
     */
    public RecyclerHolder setText(int viewId, String text) {
        TextView view = getView(viewId);
        view.setText(text);
        return this;
    }
    /**
     * 为ImageView设置图片
     *
     * @param viewId
     * @param drawableId
     * @return
     */
    public RecyclerHolder setImageResource(int viewId, int drawableId) {
        ImageView view = getView(viewId);
        view.setImageResource(drawableId);
        return this;
    }
    /**
     * 为ImageView设置图片,设置加载时图片
     *
     * @param viewId
     * @param url
     * @return
     */
    public RecyclerHolder setImageResource(int viewId, String url) {
        ImageView view = getView(viewId);
        Glide.with(view.getContext()).load(url).into(view);
        return this;
    }
    /**
     *
     *
     * 类似的方法根据自己需求自己添加
     *
     *
     */
}

在holder当中处理的更加简洁明了 ,我们可以随意的添加我们自己的需求并且使用任意的图片加载框架,不想使用Glide,我们就把他替换成picasso,是不是感觉很简单,哈哈。
使用更简单:

    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    rvContent.setLayoutManager(layoutManager);
    adapter = new ExampleAdapter(rvContent, meizis, R.layout.item_layout);
    rvContent.setAdapter(adapter);
    public class ExampleAdapter  extends BaseRecyclerAdapter<Meizi> {
        public ExampleAdapter(RecyclerView v, Collection<Meizi> datas, int itemLayoutId) {
            super(v, datas, itemLayoutId);
        }

        @Override
        public void convert(RecyclerHolder holder, Meizi item, int position) {
            holder.setImageResource(R.id.iv_item,item.getUrl());
            holder.setText(R.id.tv_item,item.getWho());
        }
     }

Demo地址: BaseRecyclerViewDemo

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值