RecyclerView 的简单封装

来源:互联网 发布:株洲知明培训学校 编辑:程序博客网 时间:2024/05/22 14:50

1 前言

最近在学习Material Design设计,首当其冲就是学习RecyclerView,参考了下Hongyang自己对RecyclerView的ViewHolder与Adapter做了下简单的封装。下面,废话不多说,直接上干货。

2 ViewHolder的封装

ViewHolder在RecyclerView中的作用主要就是用来缓存我们每一个Item对应的View视图的,我们在Adapter中主要是在public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)回去创建一个ViewHolder,在 public void onBindViewHolder(ViewHolder holder, int position)会将holder与该position处的数据进行绑定(就是设置数据该怎么显示,这里需要访问ViewHolder中缓存的View)。基于此我们可以总结出ViewHolder的基本功能:

1 提供创建ViewHolder的功能

 这里主要包括两种,一种是直接传入一个View参数创建一个View,比如我们在ListView中经常使用的下面代码:
View view = LayoutInflater.from(mContext).inflate(R.layout.xxx,parent,false);ViewHolder holder = new ViewHolder(view);
第二种就是直接传入一个layoutId,这一种我们在多种ItemType类型中经常会用到。

2 对ViewHolder中各种View的访问
一般ViewHolder中会有TextView,ImageView等,我们通过使用一个SparseArray来缓存我们加载过的View,我们经常需要对它设置文本内容,字体大小,图片内容等。

3 封装ViewHolder中各种View事件
一般主要是点击事件与长按事件,我这里只封装了点击事件

下面直接上封装好的ViewHolder

/** * Created by qiyei2015 on 2016/11/28. * 1273482124@qq.com */public class ViewHolder extends RecyclerView.ViewHolder {    private Context mContext;    private SparseArray<View> mViews;//存储View,key 为int,value为View类型    private View mConvertView;  //存储加载布局xml中的的所有View    public ViewHolder(Context context,View view){        super(view);        mContext = context;        mConvertView = view;        mViews = new SparseArray<>();    }    /**     * 创建ViewHolder,外部调用     * @param context     * @param view     * @return     */    public static ViewHolder createViewHolder(Context context,View view){        return new ViewHolder(context,view);    }    /**     * 创建ViewHolder     * @param context     * @param parent     * @param layoutId     * @return     */    public static ViewHolder createViewHolder(Context context, ViewGroup parent,int layoutId){        View itemView = LayoutInflater.from(context).inflate(layoutId,parent,false);        return new ViewHolder(context,itemView);    }    /**     * 根据id来查找View     * @param viewId     * @param <T>     * @return     */    public <T extends View> T getView(int viewId){        View view = mViews.get(viewId);        if (view == null){  //如果缓存里面没有,就从布局文件中查找            view  = mConvertView.findViewById(viewId);  //从xml查找的,减少重复调用findViewById            mViews.put(viewId,view);        }        return (T) view;    }    /**     * 获取ConvertView     * @return     */    public View getConvertView(){        return mConvertView;    }    /**     *  以下是设置TextView,imageView等View的一些常用方法     * */    /**     * 设置Text     * @param viewId     * @param text     * @return     */    public ViewHolder setText(int viewId,CharSequence text){        TextView view = getView(viewId);        view.setText(text);        return this;    }    /**     * 设置ImageView     * @param viewId     * @param resId     * @return     */    public ViewHolder setImageResource(int viewId,int resId){        ImageView view = getView(viewId);        view.setImageResource(resId);        return this;    }    /**     * 设置ImageView的bitmap     * @param viewId     * @param bitmap     * @return     */    public ViewHolder setImageBitmap(int viewId, Bitmap bitmap){        ImageView view = getView(viewId);        view.setImageBitmap(bitmap);        return this;    }    /**     * 设置View的点击事件     * @param viewId     * @param listener     * @return     */    public ViewHolder setOnClickListener(int viewId,View.OnClickListener listener){        View view = getView(viewId);        view.setOnClickListener(listener);        return this;    }}

这个就是我们封装好的ViewHolder,比较简单,使用起来还是比较方便的。使用静态方法创建对象。使用共有方法去设置对象,需要传入一个View的id值即可,可以根据项目的需要慢慢增加功能。

3 CommonAdapter的封装

CommonAdapter的封装就比较简单,主要是复写public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)和

public void onBindViewHolder(ViewHolder holder, int position)。其中有一个抽象的方法public abstract void convert(ViewHolder holder,T t,int position);这个主要是把holder与position处的数据做绑定的,这个需要子类来覆写,由子类来实现。

/** * Created by qiyei2015 on 2016/11/30. * 1273482124@qq.com */public abstract class CommonAdapter<T> extends RecyclerView.Adapter<ViewHolder> {    protected Context mContext;    protected List<T> mDatas;    protected LayoutInflater mInflater;    protected int mLayoutId;    public CommonAdapter(Context context,List<T> list,int layoutId){        mContext = context;        mDatas = list;        mInflater = LayoutInflater.from(mContext);        mLayoutId = layoutId;    }    @Override    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        ViewHolder holder = ViewHolder.createViewHolder(mContext,parent,mLayoutId);        return holder;    }    @Override    public void onBindViewHolder(ViewHolder holder, int position) {        convert(holder,mDatas.get(position),position);    }    @Override    public int getItemCount() {        return mDatas.size();    }    /**     * 设置数据     * @param data     */    public void setData(List<T> data){        mDatas = data;        notifyDataSetChanged();    }    /**     * 根据position返回对应的数据     * @param position     * @return     */    public T getItem(int position){        return mDatas.get(position);    }    /**     * 子类实现的转换方法     */    public abstract void convert(ViewHolder holder,T t,int position);}

这样子类只需要实现convert(ViewHolder holder,T t,int position)就可以了。比如:

        CommonAdapter<String> adapter = new CommonAdapter<String>() {            @Override            public void convert(ViewHolder holder, String s, int position) {                holder.setText(R.id.tv,"hello");            }        };

4 多种ItemType类型支持

在项目中,我们经常需要支持多种类型的Item的Adapter,例如今日头条的界面:
这里写图片描述
基本思想就是复写public int getItemViewType(int position),然后根据position处返回特定的type,然后在根据type类型返回响应的布局id,根据布局id生成响应的View,这样就可以实现如上图的效果了。
这里我们引入另外一个接口来支持多种类型的Item。

public interface MultiTypeItem<T> {    //根据itemType获取布局文件    int getLayoutId(int itemType);    //根据position及T 数据类型 返回对应的ItemType    int getItemType(int position,T t);}

支持多种ItemType的Adapter如下:

/** * Created by qiyei2015 on 2016/12/10. * 1273482124@qq.com */public abstract class MultiAdapter<T> extends CommonAdapter<T> {    protected MultiTypeItem<T> mMultiItemType;    public MultiAdapter(Context context, List<T> datas, MultiTypeItem<T> itemType){        super(context,datas,-1);        mMultiItemType = itemType;    }    @Override    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        int id = mMultiItemType.getLayoutId(viewType);        return ViewHolder.createViewHolder(mContext,parent,id);    }    @Override    public void onBindViewHolder(ViewHolder holder, int position) {        super.onBindViewHolder(holder, position);    }    /**     * 返回position 对应的type     * @param position     * @return     */    @Override    public int getItemViewType(int position) {        return mMultiItemType.getItemType(position,getItem(position));    }}

使用也很简单,首先新建一个MultiTypeItem对象。然后新建MultiAdapter实例即可。

0 0