天天看点

对RecyclerView的Adapter进行抽取

当项目当中遇到了很多个页面都要用到列表的时候,我们可能会用到ListView又或者用到RecyclerView,其实不管用到哪个控件来实现,adapter和hodler是必须要用到的,每写一个ListView或者RecyclerView,都要去实现一个adapter和hodler,显然有很多重复的代码,那么能不能把共有的方法抽取出来呢,显然是可以的,ListView的抽取以前写过,地址是: http://blog.csdn.net/ming_147/article/details/62892727,这边文章主要是叙述RecyclerView的抽取。

RecyclerView的Adapter是继承于RecyclerView.Adapter<BaseAdapter.ViewHolder>,ViewHolder在这里我是以泛型的形式引入进来,并在BaseAdapter类中具体实现,如下:

public class BaseAdapter extends RecyclerView.Adapter<BaseAdapter.ViewHolder>{
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return null;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

    }

    @Override
    public int getItemCount() {
        return 0;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public ViewHolder(View itemView) {
            super(itemView);
        }
    }
}      

好了,具体就这些方法,那么该如何去下手呢,我们可以先分析一下,要实现一个Adapter,我们都需要哪些条件呢?首先数据是必不可少的,一般是以集合的形式传入,这里我们可以从构造方法里传进,集合确定,而类型不能确定,我们可以用D来标识,实例变量携带泛型,记得给类也加上泛型,这里我写了一个空的接口,用来做双向绑定,如下:

public class BaseAdapter<D extends IModel> extends RecyclerView.Adapter<BaseAdapter.ViewHolder> {
    private List<D> dataList;

    public BaseAdapter(List<D> dataList) {
        this.dataList = dataList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return null;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

    }

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

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public ViewHolder(View itemView) {
            super(itemView);
        }
    }
}      

数据传入了,那么还少什么呢,对,View视图,这里我把BaseAdapter改成了抽象类,并实现获取view的一个抽象方法,并在onCreateViewHolder方法里进行使用,如下:

public abstract int getLayoutId();

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(getLayoutId(),parent,false);
    BaseAdapter.ViewHolder vh = new BaseAdapter.ViewHolder(view);
    return vh;
}      

接下来,就是向外继续抽象一个方法,用于数据的绑定,其实就是把onBindViewHolder方法,抽象到外面自己来实现其里面的功能:

public abstract void createHolder(BaseAdapter.ViewHolder holder, D d);

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        createHolder(holder,dataList.get(position));
    }      

目前为止,adapter里已经抽取完成,下面看下ViewHolder里,其实在ViewHolder里,主要用于获取控件:

public static class ViewHolder extends RecyclerView.ViewHolder {
        private View rootView;
        private SparseArray<View> views=new SparseArray<>();
        public ViewHolder(View itemView) {
            super(itemView);
        }
        public <T extends View> T get(int id){
            T view=(T)views.get(id);
            if(view==null){
                view=(T)rootView.findViewById(id);
                views.put(id,view);
            }
            return view;
        }
        //TextView设置数据
        public void setText(int viewId, String txt) {
            TextView mTextView = get(viewId);
            mTextView.setText(txt);
        }
        //设置图片
        public void setPic(int viewId, String url) {
            ImageView mImageView = get(viewId);
            Picasso.with(mContext).load(url).fit().error(R.drawable.ic_launcher).placeholder(mImageView.getDrawable()).memoryPolicy(MemoryPolicy.NO_CACHE).into(mImageView);
        }
    }      

这里我写了两个方法setText和setPic,主要目的就是简便我们的代码,方便我们调用,到这里,我们这个BaseAdapter,已经抽取完成了,下面看一下整个类:

/**
 * Created by AbnerMing on 2017/12/29.
 */

public abstract class BaseAdapter<D extends IModel> extends RecyclerView.Adapter<BaseAdapter.ViewHolder> {
    private List<D> dataList;

    public abstract int getLayoutId();

    public BaseAdapter(List<D> dataList) {
        this.dataList = dataList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(getLayoutId(),parent,false);
        BaseAdapter.ViewHolder vh = new BaseAdapter.ViewHolder(view);
        return vh;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        createHolder(holder,dataList.get(position));
    }

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

    public abstract void createHolder(BaseAdapter.ViewHolder holder, D d);

    public static class ViewHolder extends RecyclerView.ViewHolder {
        private View rootView;
        private SparseArray<View> views=new SparseArray<>();
        public ViewHolder(View itemView) {
            super(itemView);
        }
        public <T extends View> T get(int id){
            T view=(T)views.get(id);
            if(view==null){
                view=(T)rootView.findViewById(id);
                views.put(id,view);
            }
            return view;
        }
        //TextView设置数据
        public void setText(int viewId, String txt) {
            TextView mTextView = get(viewId);
            mTextView.setText(txt);
        }
        //设置图片
        public void setPic(int viewId, String url) {
            ImageView mImageView = get(viewId);
            Picasso.with(mContext).load(url).fit().error(R.drawable.ic_launcher).placeholder(mImageView.getDrawable()).memoryPolicy(MemoryPolicy.NO_CACHE).into(mImageView);
        }
    }
}      

具体调用:

public class MyAdapter extends BaseAdapter<Bean>{
    public MyAdapter(List<Bean> dataList) {
        super(dataList);
    }

    @Override
    public int getLayoutId() {
        return 0;
    }

    @Override
    public void createHolder(BaseAdapter.ViewHolder holder, Bean bean) {

    }
}      

以后所有的Adapter都可以去继承BaseAdapter,只仅仅的实现两个方法就ok了,是不是方便多了。