打造通用的recycleview的adapter

通用RecyclerView Adapter设计
本文介绍了一种基于RecyclerView的通用Adapter设计方法,支持单布局及多布局,并提供了详细的代码实现及示例,便于开发者快速上手。

   本人之前也是不喜欢写博客,可是发现好多知识当时知道过了很长时间就会忘记,又得回去找资料看,最近看一些资料,觉得用recycleview每次写adapter 就很麻烦,看了不是的博客,自己也了已个通用的adapter,这个还是收到Darren的启发,确实要自己总结一下自己的知识,就写这个通用的adapter,第一次写写得不好,看到的希望对你有帮助,可以互相学习。

基本思路:

 要让adapter通用的话,要解决布局,数据,r绑定怎么搞?数据的话可以通过泛型来传递,布局的话可以通过构造传,绑定显示就可以回传


1:改造adapter  下面是一个通用的adapter 他实现了单布局和多布局


/**
 * Created by Administrator on 2017/7/11 0011.
 *
 * Description: 通用的Adapter
 */
public abstract class CommonAdapter<DATA> extends RecyclerView.Adapter<ViewHodle>{
    private int mLayoutId;
    protected List<DATA> mDatas;
    private LayoutInflater mLayoutInfater;
    private Context mContext;
    private  MulitiTypeSupport typeSupport;
   //这个是普通布局就可以调用这个方法
    public CommonAdapter(Context mContext,int mLayoutId, List<DATA> mDatas) {
        mLayoutInfater = LayoutInflater.from(mContext);
        this.mContext = mContext;
        this.mLayoutId = mLayoutId;
        this.mDatas = mDatas;
    }
    //这个是多布局
    public CommonAdapter(Context mContext,List<DATA> mDatas, MulitiTypeSupport typeSupport ){
        this(mContext,-1,mDatas);
        this.typeSupport = typeSupport;

    }

    @Override
    public ViewHodle onCreateViewHolder(ViewGroup parent, int viewType) {
        if(typeSupport!=null){//需要多布局
            mLayoutId = viewType;
        }
        View itemView = mLayoutInfater.inflate(mLayoutId,parent,false);
        ViewHodle viewHodle = new ViewHodle(itemView);
        return viewHodle;
    }

    @Override
    public int getItemViewType(int position) {
        //多布局用
        if(typeSupport!=null){
            return typeSupport.getLayoutId(mDatas.get(position));
        }
        return super.getItemViewType(position);
    }

    @Override
    public void onBindViewHolder(ViewHodle holder, final int position) {
        convert(holder,mDatas.get(position),position);
        if(itemClickListeren!=null){
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    itemClickListeren.itemClick(position);
                }
            });
        }

        if(onItemLongClickListeren!=null){
            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    onItemLongClickListeren.onItemLongClick(position);
                    return true;
                }
            });
        }


    }
   //这个方法是把数据 ViewHolder 还有当前的位置传出去  实现在你自己的adapter里面
    protected abstract void convert(ViewHodle holder, DATA data, int position);



    @Override
    public int getItemCount() {
        return mDatas.size();
    }
   //recycleview的点击跟长按事件
   private ItemClickListener itemClickListeren;
    public void setOnItemClickListeren(ItemClickListener itemClickListeren){
        this.itemClickListeren = itemClickListeren;
    }
    private OnItemLongClickLiateren onItemLongClickListeren;
    public  void setOnItemLongClickListeren(OnItemLongClickLiateren onItemLongClickListeren){
        this.onItemLongClickListeren = onItemLongClickListeren;
    }
    //这个是数据刷新 添加数据 
    public void upData(List<DATA> mDatas){
       this.mDatas = mDatas;
       notifyDataSetChanged();
     }
}

 

2:下面是我自己写的一个例子

/**
 * Created by Administrator on 2017/7/11 0011.
 * Description: 通用的Adapter
 */
//在集成通用的adapter的时候 数据传递是根据你自己的数据格式传递
public class TextAdapter extends CommonAdapter<A.Data> {
    //我们继承的时候 会继承单布局 和多布局 这里是多布局
    /*
     * mContext  上下文
     * mDatas 数据
    * typeSupport 布局的类型
    *  这里我们可以不用这种 直接 MulitiTypeSupport 这个直接new出来
    */
   /* public TextAdapter(Context mContext, List<A.Data> mDatas, MulitiTypeSupport typeSupport) {
        super(mContext, mDatas, typeSupport);
    }*/
        public TextAdapter(Context mContext, final List<A.Data> mDatas) {
        super(mContext, mDatas, new MulitiTypeSupport<A.Data>() {
            @Override
            public int getLayoutId(A.Data item) {
                //我这里只是用了2种布局
                if (item.position == 1) {
                    return R.layout.item_1;
                }
                return R.layout.item_0;
            }
        });
    }

    // //我们继承的时候 会继承单布局 和多布局 这里是单布局  单布局实现就很简单了  数据
    /*
    * mContext  上下文
    * mLayoutId  布局id
    * mDatas   数据
    */
    /*public TextAdapter(Context mContext, int mLayoutId, List<A.Data> mDatas) {
        super(mContext, mLayoutId, mDatas);
    }*/



    /*
    * holder viewholder
    * data  数据
    * position  当前的位置
    */
    @Override
    protected void convert(ViewHodle holder, A.Data data, int position) {
        if (data.position == 1) {
            holder.setText(R.id.tv1, data.content);
        } else if (data.position == 0) {
            holder.setText(R.id.tv0, data.content);
        }
        //这里是调用显示网络图片
//        holder.setImagePath(R.id.tv0, data.content,new ImageLoad(data.content) )
/*
* 图片处理
* */
    public class ImageLoad extends ViewHodle.HolderImageLoader {

       public ImageLoad(String path) {
           super(path);
       }

       @Override
       public void loadImage(Context context, ImageView imageView, String path) {
           //这里你可以用Glide 也可以用其他第三方的网络加载图片
           Glide.with(context).load(path).into(imageView);
        }
     }
}


3:最后就是ViewHolder 直接贴代码

/**
 * Created by Administrator on 2017/7/11 0011.
 * Description: RecyclerView的ViewHolder
 */
public class ViewHodle extends RecyclerView.ViewHolder{
    //通过 SparseArray<View> 来缓存 不用每次都去findViewById
    private SparseArray<View> mViews;
    public ViewHodle(View itemView) {
        super(itemView);
        mViews = new SparseArray<>();
    }
    /*
    * getView 这个方法是去 findViewById 不用你在外面去findViewById 减少代码
    *
    */
    public <T extends View> T  getView(int viewId){
        View view = mViews.get(viewId);
        if(view == null){
            view = itemView.findViewById(viewId);
            mViews.put(viewId,view);
        }
        return (T)view;
    }
 /*
    * setText  这个方法是直接调用设置TextView
    * viewId  TextView 的id
    * text   TextView 的数据
    */
    public ViewHodle setText(int viewId,String text){
        TextView view = getView(viewId);
        view.setText(text);
        return this;
    }
    //处理本地图片
    public ViewHodle setImageResource(int viewId,int resource){
        ImageView view  =getView(viewId);
        view.setImageResource(resource);
        return this;
    }
    /**
     * 设置图片通过路径,这里稍微处理得复杂一些,因为考虑加载图片的第三方可能不太一样
     * 也可以直接写死
     */
   
 public ViewHodle setImagePath(int viewId, String path,HolderImageLoader imageLoader){
        ImageView view  =getView(viewId);
        //这里是写死的
//        Glide.with(view.getContext()).load(path).into(view);
        if(imageLoader == null) {
            throw new NullPointerException("imageLoader is null!");
        }
        imageLoader.loadImage(view.getContext(),view,imageLoader.getmPath());
        return this;
    }
   

  }

 
  /**
     * 图片加载,这里稍微处理得复杂一些,因为考虑加载图片的第三方可能不太一样
     * 也可以不写这个类
     */
    public abstract static class HolderImageLoader{
        private String mPath;

        public String getmPath() {
            return mPath;
        }

        public HolderImageLoader(String path) {
            this.mPath = path;
        }
        public abstract void loadImage(Context context,ImageView imageView,String path);
    }






4:最后调用
/**
 * Created by Administrator on 2017/7/11 0011.
 */
public class A extends AppCompatActivity{

    private RecyclerView rl;
    List<Data> list ;
    private TextAdapter adapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        list = new ArrayList<>();
        for (int i=0;i<50;i++){
            if(i%3==0){
                list.add(new Data("我是布局1的数据"+i,1));
            }else {
                list.add(new Data("我是布局0的数据"+i,0));
            }
        }
        rl = (RecyclerView) findViewById(R.id.recycle);
        rl.setLayoutManager(new LinearLayoutManager(this));
        adapter = new TextAdapter(this, list);

        rl.setAdapter(adapter);
     adapter.setOnItemClickListeren(new ItemClickListener() {
         @Override
         public void itemClick(int position) {
             Toast.makeText(A.this,"你点击了第"+position+"个条目",Toast.LENGTH_SHORT).show();
         }
     });
        adapter.setOnItemLongClickListeren(new OnItemLongClickLiateren() {
            @Override
            public void onItemLongClick(int position) {
                Toast.makeText(A.this,"你长按了第"+position+"个条目",Toast.LENGTH_SHORT).show();
            }
        });
    }
/*
* 这个方法是添加数据 这里没有上啦  就模拟点击加载数据
*/
    public void n(View view) {
        List<Data> da = new ArrayList<>();
        for (int i=0;i<50;i++){
            if(i%3==0){
                da.add(new Data("我是添加布局1的数据"+i,1));

            }else {
                da.add(new Data("我是添加布局0的数据"+i,0));
            }
        }
        list.addAll(da);
        adapter.upData(list);

    }


    public class Data{
        String content;
        int position;

        public Data(String content, int position) {
            this.content = content;
            this.position = position;
        }
    }
}

以上是全部代码 都测试过 单布局跟多布局


















                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值