打造通用的recycleview的adapter

来源:互联网 发布:java base64 转换 编辑:程序博客网 时间:2024/06/07 23:13

   本人之前也是不喜欢写博客,可是发现好多知识当时知道过了很长时间就会忘记,又得回去找资料看,最近看一些资料,觉得用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;        }    }}

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