学习笔记之----Adapter的封装(RecyclerView)

前言:因为RecyclerView在项目中要经常使用,故而为了方便而封装

一,四步骤:

1,数据要使用泛型

2,数据绑定通过实现抽象方法来实现

3,ViewHolder中的View成员变量转而通过view数组来实现

4,基类里面提供常用的方法


以,上一篇文章RecyclerView+MaterialRefreshLayout为例,

上一篇链接:http://blog.csdn.net/qq_28055429/article/details/59539073

二,代码如下:

(1)先建立类BaseViewHolder 继承RecyclerView.ViewHolder,代码如下:

public class BaseViewHolder extends RecyclerView.ViewHolder {
    public BaseViewHolder(View itemView) {
        super(itemView);
    }
}
(2)创建BaseAdapter

之前创建Adapter,主要格式如下:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>
现在BaseAdapter格式如下:( 主要里面变量为protected,因为是基类)

public abstract  class BaseAdapter<T , H extends BaseViewHolder> extends RecyclerView.Adapter<BaseViewHolder> {}

然后再在里面添加代码,具体如下:

/**基类:封装RecyclerView.Adapter
 * Created by maiyu on 2017/3/5.
 */
public abstract  class BaseAdapter<T , H extends BaseViewHolder> extends RecyclerView.Adapter<BaseViewHolder> {

    protected List<T> mDatas ;                  //定义List<>集合,参数为泛型
    protected final Context mContext ;            //上下文对象
    protected final LayoutInflater mInflater ;    //LayoutInflater对象
    protected final int mLayoutResId ;            //传入的布局id

    protected OnItemClickListener listener ;    //定义监听器接口


    /**
     * 初始化数据
     * @param context
     * @param datas
     * @param layoutResId
     */
    public BaseAdapter(Context context , List<T> datas  ,int layoutResId ){
        this.mDatas     =   datas ;             //初始化List<T>数据
        this.mContext   =   context ;           //初始化上下文
        this.mLayoutResId   =   layoutResId ;

        mInflater   =   LayoutInflater.from(context);       //获取Inflater对象
    }

    /**
     * 创建ViewHolder
     * @param parent
     * @param viewType
     * @return
     */
    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        //获取View
        View    view    =   mInflater.inflate(mLayoutResId , null , false);
        return new BaseViewHolder(view , listener);         //创建BaseViewHolde
    }

    /**
     * 绑定ViewHolder
     * @param holder
     * @param position
     */
    @Override
    public void onBindViewHolder(BaseViewHolder holder, int position) {

        T   t  = getItem(position);     //获取当前T对象
        bindData(holder ,t);            //绑定
    }

    /**
     * 返回长度
     * @return
     */
    @Override
    public int getItemCount() {
        if(mDatas == null || mDatas.size() <= 0){
            return 0;
        }
        return mDatas.size();
    }

    /**
     * 获取当前子项
     * @param position
     * @return
     */
    public T getItem(int position){

        if(position >= mDatas.size()){
            return null;
        }return mDatas.get(position);
    }

    //定义一个抽象类型的方法
    public  abstract  void bindData(BaseViewHolder viewHolder , T t);


    //接口
    public  interface  OnItemClickListener  {
        void OnClick(View view , int position);
    }

    //设置接口
    public void setOnItemClickListener(OnItemClickListener listener){
        this.listener   =   listener ;
    }


    //以下这几个方法根据需要去添加,因为上一个例子中有用到
    /**
     * 获取数据
     * @return
     */
    public List<T> getDatas(){

        return  mDatas;
    }

    /**
     * 清除数据
     */
    public void clearData(){

        mDatas.clear();
        notifyItemRangeRemoved(0,mDatas.size());
    }

    /**
     * 添加数据
     * @param datas
     */
    public void addData(List<T> datas){

        addData(0,datas);
    }

    /**
     * 添加数据
     * @param position
     * @param datas
     */
    public void addData(int position,List<T> datas){

        if(datas !=null && datas.size()>0) {

            mDatas.addAll(datas);
            notifyItemRangeChanged(position, mDatas.size());
        }

    }
}
后面那几个方法因为上一个例子其他代码需要,故而添加了-------就是采用方法,

如果,不需要监听器,也可以不添加;

现在BaseAdapter已经基本成形,只差添加你需要常用的相关方法了。

(3)现在要回到BaseViewHolder类中,为控件绑定id了,具体代码如下,

/**基类:BaseViewHolder继承RecyclerView.ViewHolder
 * Created by maiyu on 2017/3/5.
 */
public class BaseViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    //因为不知道是什么控件,多少控件,故而用SparseArray<View>数组来存放View
    private SparseArray<View> views;                     //存放一系列View
    protected BaseAdapter.OnItemClickListener listener;    //定义监听器

    /**
     * 初始化数据
     *
     * @param itemView
     * @param listener
     */
    public BaseViewHolder(View itemView, BaseAdapter.OnItemClickListener listener) {
        super(itemView);

        views = new SparseArray<View>();        //初始化数组
        this.listener = listener;              //初始化监听
        itemView.setOnClickListener(this);          //设置监听
    }

    /**
     * 获取View
     *
     * @param id
     * @return
     */
    public View getView(int id) {
        return findView(id);
    }

    /**
     * 根据id找到View,返回泛型数据
     *
     * @param id
     * @param <T>
     * @return
     */
    protected <T extends View> T findView(int id) {
        //找到相应view对象
        View view = views.get(id);
        //若为空
        if (view == null) {
            //初始化该view
            view = itemView.findViewById(id);
            //添加到views数组中
            views.put(id, view);
        }
        return (T) view;
    }

    /**
     * 监听器
     *
     * @param view
     */
    @Override
    public void onClick(View view) {
        if (listener != null) {
            //为当前view根据布局中的相应位置设置监听
            listener.OnClick(view, getLayoutPosition());
        }
    }
    
}
若无需监听,也可以去掉,现在该ViewHolder也差添加相应常用方法,

(4)现在就可以在TestActivity中,直接使用了

用方法

        mRecyclerView.setAdapter(new BaseAdapter<String , BaseViewHolder>(getBaseContext(),list ,R.layout.item) {
            @Override
            public void bindData(BaseViewHolder viewHolder, String s) {
                //找到控件并设置,
                TextView textView = viewHolder.getTextView(R.id.text);
                Log.d("TestActivity", s + "");
                textView.setText(s);
                //但是如果这里有n个控件,那么是不是需要重复这样写呢??
            }
        });
但是你会发现问题:

No adapter attached; skipping layout

然后再在设置完适配器之后添加如下代码就可以了

        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());

但是,如果有好多个控件,,,那么重复代码要好多,于是就要添加常用方法,在BaseViewHolder中添加代码如下:

(这里以按钮,图片,文本为例)

/**
     * 获取TextView
     * @param id
     * @return
     */
    public TextView getTextView(int id){
        return findView(id);
    }

    /**
     * 获取ImageView
     * @param id
     * @return
     */
    public ImageView getImageView(int id){
        return findView(id);
    }

    /**
     * 获取Button
     */
    public Button getButton(int id){
        return findView(id);
    }
这时代码就可以直接设置了:

 viewHolder.getTextView(R.id.text).setText(s + "");

但是,你会发现,用new BaseAdapter()方法并设置参数有点复杂,好不方便,故而
可以,再创建一个基类,这里命名SimpleAdapter,继承BaseAdapter,并传入相关泛型参数,如下:

public abstract class SimpleAdapter<T> extends BaseAdapter<T , BaseViewHolder> {
    public SimpleAdapter(Context context, List<T> datas, int layoutResId) {
        super(context, datas, layoutResId);
    }

}

这样用起来比较简单:

        mRecyclerView.setAdapter(new SimpleAdapter<String>(getBaseContext(),list ,R.layout.item) {
            @Override
            public void bindData(BaseViewHolder viewHolder, String s) {
                //写代码
                viewHolder.getTextView(R.id.text).setText(s + "");
            }
        });


是不是简单了许多,但是突然发现在里面添加为控件添加监听器时,因为是内部类关系,数值不能传过来,于是必须定义final变量取值,
这样又多了代码了,故而

(5)再创建一个类:TSAdapter继承SimpleAdapter<你要的数据类型>:

public class TSAdapter extends SimpleAdapter<String> {
    public TSAdapter(Context context, List<String> datas) {
        super(context, datas, R.layout.item);

    }

    @Override
    public void bindData(BaseViewHolder viewHolder, String s) {
        viewHolder.getTextView(R.id.text).setText(s + "");
    }
}

于是这样多简单:

        //初始化适配器
        adapter =   new TSAdapter( getBaseContext() ,list);
        adapter.setOnItemClickListener(new BaseAdapter.OnItemClickListener() {
            @Override
            public void OnClick(View view, int position) {

            }
        });
        //为RecyclerView绑定适配器
        mRecyclerView.setAdapter(adapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
这样,适配器自定义就好了,这里当你别的RecyclerView控件需要设置时,是不是就不需要在创建适配器了呢?
只需要创建一个执行第(5)步,即创建一个继承自SimpleAdapter,并设置数据,即可




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值