属于RecyclerView的万能适配器Adapter和ViewHolder

来源:互联网 发布:校园网mac地址克隆 编辑:程序博客网 时间:2024/05/17 22:45
所有分类  >  开发语言与工具  >  移动开发  >  Android开发

属于RecyclerView的万能适配器Adapter和ViewHolder

  2016-02-17 09:14:58 发布
您的评价:
     
5.0
收藏     1收藏

来自: http://blog.csdn.net/tellh/article/details/50670458


前言

昨天开始接触江湖口碑很好的RecyclerView,事实上,我已经被她的强大所征服了!资源回收,数据绑定,布局显示,分割线,Item动画多个模块高度解耦,灵活优雅。其实,RecyclerView在使用上已经是相当简单了(个人觉得),但仍有很多代码是可以加以封装的。今天受简书上一篇博文的启发,作为写代码喜欢优(tou)雅(lan)的人,想到了一种封装方式,打造万能适配器,供大家食用。

正统模式:

public class SimplerItemAdapter extends RecyclerView.Adapter<SimplerItemAdapter.SimpleItemViewHolder > {  private List <String> items;  public SimplerItemAdapter (@NonNull List<String> dateItems ) {    this.items = (dateItems != null ? dateItems : new ArrayList<String>());  }  @Override public SimpleItemViewHolder onCreateViewHolder (ViewGroup viewGroup, int viewType) {    View itemView = LayoutInflater.from( viewGroup.getContext ()).inflate(R.layout .item, viewGroup, false );    return new SimpleItemViewHolder(itemView);  }  @Override public void onBindViewHolder (SimpleItemViewHolder viewHolder, int position) {    viewHolder.textView .setText(items.get (position));  }  @Override public int getItemCount () {    return (this.items != null) ? this .items. size() : 0 ;  }  protected final static class SimpleItemViewHolder extends RecyclerView.ViewHolder {    protected TextView textView ;    public SimpleItemViewHolder (View itemView) {      super(itemView);      this.textView = (TextView) itemView.findViewById (R. id.text);    }  }}
  • 首先, 
    @Override public int getItemCount () { 
    return (this.items != null) ? this .items. size() : 0 ; 
    }
    这段代码完全可以封装起来的。
  • onCreatedViewHolder()方法作用是绑定item视图,可以进一步封装,给子类提供一个getLayoutItemId的抽象方法,这样就可以简化成一行代码了。
  • 因此我们发现,这个adapter的核心代码在与onBindViewHolder()中,作用是将数据跟视图(ViewHolder)绑定,可以给子类提供一个bindData()抽象方法。
  • 当然了,使用泛型也是极好的,拓广了adapter的使用范围。
  • 添加点击事件的监听也可以封装到万能adapter中,子类就不用再写item点击事件处理代码了

封装后的Adapter

public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerViewHolder> {    protected final List<T> mData;    protected final Context mContext;    protected LayoutInflater mInflater;    private OnItemClickListener mClickListener;    private OnItemLongClickListener mLongClickListener;    public BaseRecyclerAdapter(Context ctx, List<T> list) {        mData = (list != null) ? list : new ArrayList<T>();        mContext = ctx;        mInflater = LayoutInflater.from(ctx);    }    @Override    public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        final RecyclerViewHolder holder = new RecyclerViewHolder(mContext,                mInflater.inflate(getItemLayoutId(viewType), parent, false));        if (mClickListener != null) {            holder.itemView.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    mClickListener.onItemClick(holder.itemView, holder.getLayoutPosition());                }            });        }        if (mLongClickListener != null) {            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {                @Override                public boolean onLongClick(View v) {                    mLongClickListener.onItemLongClick(holder.itemView, holder.getLayoutPosition());                    return true;                }            });        }        return holder;    }    @Override    public void onBindViewHolder(RecyclerViewHolder holder, int position) {        bindData(holder, position, mData.get(position));    }    @Override    public int getItemCount() {        return mData.size();    }    public void add(int pos, T item) {        mData.add(pos, item);        notifyItemInserted(pos);    }    public void delete(int pos) {        mData.remove(pos);        notifyItemRemoved(pos);    }    public void setOnItemClickListener(OnItemClickListener listener) {        mClickListener = listener;    }    public void setOnItemLongClickListener(OnItemLongClickListener listener) {        mLongClickListener = listener;    }    abstract public int getItemLayoutId(int viewType);    abstract public void bindData(RecyclerViewHolder holder, int position, T item);    public interface OnItemClickListener {        public void onItemClick(View itemView, int pos);    }    public interface OnItemLongClickListener {        public void onItemLongClick(View itemView, int pos);    }}

Super ViewHolder!

其实,这还没完呢!重头戏在ViewHolder上!RecyclerView强制我们使用ViewHolder模式,然而缺不可避免地要写findViewById代码,有没有办法不写这样的代码呢?甚至连ViewHolder都不写呢?当然可以!

public class RecyclerViewHolder extends RecyclerView.ViewHolder {    private SparseArray<View> mViews;//集合类,layout里包含的View,以view的id作为key,value是view对象    private Context mContext;//上下文对象    public RecyclerViewHolder(Context ctx, View itemView) {        super(itemView);        mContext = ctx;        mViews = new SparseArray<View>();    }    private <T extends View> T findViewById(int viewId) {        View view = mViews.get(viewId);        if (view == null) {            view = itemView.findViewById(viewId);            mViews.put(viewId, view);        }        return (T) view;    }    public View getView(int viewId) {        return findViewById(viewId);    }    public TextView getTextView(int viewId) {        return (TextView) getView(viewId);    }    public Button getButton(int viewId) {        return (Button) getView(viewId);    }    public ImageView getImageView(int viewId) {        return (ImageView) getView(viewId);    }    public ImageButton getImageButton(int viewId) {        return (ImageButton) getView(viewId);    }    public EditText getEditText(int viewId) {        return (EditText) getView(viewId);    }    public RecyclerViewHolder setText(int viewId, String value) {        TextView view = findViewById(viewId);        view.setText(value);        return this;    }    public RecyclerViewHolder setBackground(int viewId, int resId) {        View view = findViewById(viewId);        view.setBackgroundResource(resId);        return this;    }    public RecyclerViewHolder setClickListener(int viewId, View.OnClickListener listener) {        View view = findViewById(viewId);        view.setOnClickListener(listener);        return this;    }}

该类的核心方法是private T findViewById(int viewId),核心成员变量是private SparseArray mViews; 不信可以不写一句ViewHolder代码?接下来看看用法。

实践用法

添加Adapter仅需短短的几行代码:

Adapter = new BaseRecyclerAdapter<String>(this,mDataList) {            @Override            public int getItemLayoutId(int viewType) {                return R.layout.item;            }            @Override            public void bindData(RecyclerViewHolder holder, int position,String item) {                //调用holder.getView(),getXXX()方法根据id得到控件实例,进行数据绑定即可                holder.setText(R.id.tv_num,item)                        .getTextView(R.id.tv_title,item).setText(item);            }        };

完整代码:

    private void init() {        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);        mDataList = new ArrayList<>();        for (int i = 0; i <= 100; i++) {            mDataList.add(String.valueOf(i));        }        //设置item动画        recyclerView.setItemAnimator(new DefaultItemAnimator());        mAdapter = new BaseRecyclerAdapter<String>(this,mDataList) {            @Override            public int getItemLayoutId(int viewType) {                return R.layout.item;            }            @Override            public void bindData(RecyclerViewHolder holder, int position,String item) {                //调用holder.getView(),getXXX()方法根据id得到控件实例,进行数据绑定即可                holder.setText(R.id.tv_num,item)                        .getTextView(R.id.tv_title,item).setText(item);            }        };        recyclerView.setAdapter(mAdapter);        //添加item点击事件监听        ((BaseRecyclerAdapter)mAdapter).setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener() {            @Override            public void onItemClick(View itemView, int pos) {                Toast.makeText(AdapterTestActivity.this, "click " + pos, Toast.LENGTH_SHORT).show();            }        });        ((BaseRecyclerAdapter)mAdapter).setOnItemLongClickListener(new BaseRecyclerAdapter.OnItemLongClickListener() {            @Override            public void onItemLongClick(View itemView, int pos) {                Toast.makeText(AdapterTestActivity.this, "long click " + pos, Toast.LENGTH_SHORT).show();            }        });        //设置布局样式LayoutManager        recyclerView.setLayoutManager(new LinearLayoutManager(AdapterTestActivity.this, LinearLayoutManager.VERTICAL, false));// recyclerView.addItemDecoration(new ItemDividerDecoration(MainActivity.this, OrientationHelper.VERTICAL));    }

如果觉得有什么不妥之处或建议,敬请指教! 
完整项目代码已上传至Github。—Github跳转。

see also: 
Listview的Adapter应该这样写

阅读目录

  • 前言
  • 正统模式:
  • 封装后的Adapter
  • Super ViewHolder!
  • 实践用法
原创粉丝点击