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

来源:互联网 发布:最新网络神曲排行榜 编辑:程序博客网 时间:2024/05/23 12:39

相信用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 0
原创粉丝点击