在Android开发,特别是电商项目开发,使用RecyclerView、ListView、GridView是正常不过的了。一个项目下来,基本就是一直在写Adapter。刚开始写Adapter觉得没什么,无非就是ListView的继承BaseAdapter复写几个方法,getView里面使用ViewHolder模式;RecyclerView的就继承 RecyclerView.Adapter,复写onCreateViewHolder、onBindViewHolder然后实现便完事。但当我写到10遍、100遍甚至更多的时候,我就不想写了,反正都是这种写法,也没什么新的套路。于是我就想写一个RecyclerView、ListView、GridView通用的Adapter。

在文章最后附上DEMO

项目运行的实际效果:左边是ListView,右边是RecyclerView。

二、常见ListView、RecyclerView Adapter写法的例子

代码没什么难度可以随便看看就好。

public class ListViewAdapter extends BaseAdapter  {      private LayoutInflater mInflater;      private Context mContext;      private List mDatas;      private int mLayoutId;      public ListViewAdapter(Context context, List mDatas,int layoutId)      {          mInflater = LayoutInflater.from(context);          this.mContext = context;          this.mDatas = mDatas;          this.mLayoutId = layoutId;    }        @Override      public int getCount()      {          return mDatas.size();      }        @Override      public Object getItem(int position)      {          return mDatas.get(position);      }        @Override      public long getItemId(int position)      {          return position;      }        @Override      public View getView(int position, View convertView, ViewGroup parent)      {          ViewHolder viewHolder = null;          if (convertView == null)          {              convertView = mInflater.inflate(R.mLayoutId, parent, false);              viewHolder = new ViewHolder();              viewHolder.mTextView = (TextView) convertView                      .findViewById(R.id.id_tv);              convertView.setTag(viewHolder);          } else          {              viewHolder = (ViewHolder) convertView.getTag();          }          viewHolder.mTextView.setText(mDatas.get(position));          return convertView;      }        private final class ViewHolder      {          TextView mTextView;      }    }  private class RecyclerAdapter extends RecyclerView.Adapter {    private LayoutInflater mInflater;    private Context mContext;    private List mData;    private int mLayoutId;    public RecyclerAdapter(Context context, List data, int layoutId) {        mInflater = LayoutInflater.from(context);        this.mContext = context;        this.mData = data;        this.mLayoutId = layoutId;    }    @Override    public Holder onCreateViewHolder(ViewGroup parent, int viewType) {        View view = mInflater.inflate(mLayoutId, parent, false);        return new Holder(view);    }    @Override    public void onBindViewHolder(Holder holder, int position) {        holder.tv.setText(mData.get(position));    }    @Override    public int getItemCount() {        return mData.size();    }    class Holder extends RecyclerView.ViewHolder {        public TextView tv;        public Holder(View itemView) {            super(itemView);            tv = itemView.findViewById(R.id.tv);        }    }}

三、ListView、RecyclerView Adapter一些共性分析

1. 要显示的条目个数2. 要显示和条目对应的类型3. ListView、RecyclerView中,总共有多少个条目类型4. 根据不同的条目类型加载不同的View5. ListView复用条目convertView,RecyclerView自带ViewHoler复用

四、抽取RecyclerView、ListView、GridView适配器的基类

由于要通用RecyclerView、ListView、GridView只能将RecyclerView.Adapter和ListAdapter,SpinnerAdapter
这些都给实现了。里面也没多少个方法,其实也是很简单。至于一些方法的实现我考贝BaseAdapter的实现,
大家可以去看看BaseAdapter的源码。

public class BaseAdapter extends RecyclerView.Adapter implements ListAdapter, SpinnerAdapter {    private final DataSetObservable mDataSetObservable = new DataSetObservable();    // RecyclerView========================================================================    @Override    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        return null;    }    // RecyclerView    @Override    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {    }    // RecyclerView    @Override    public int getItemCount() {        return 0;    }    // RecyclerView========================================================================    // ListView========================================================================    @Override    public boolean areAllItemsEnabled() {        return true;    }    @Override    public boolean isEnabled(int position) {        return true;    }    @Override    public void registerDataSetObserver(DataSetObserver observer) {        mDataSetObservable.registerObserver(observer);    }    @Override    public void unregisterDataSetObserver(DataSetObserver observer) {        mDataSetObservable.unregisterObserver(observer);    }    public void notifyListDataSetChanged() {        mDataSetObservable.notifyChanged();    }    @Override    public Object getItem(int position) {        return null;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        return null;    }    @Override    public int getViewTypeCount() {        return 1;    }    @Override    public int getItemViewType(int position) {        return 0;    }    @Override    public int getCount() {        return 0;    }        @Override    public boolean isEmpty() {        return getCount() == 0;    }    @Override    public View getDropDownView(int position, View convertView, ViewGroup parent) {        return getView(position, convertView, parent);    }}

五、抽取支持ListView、 GridView、 RecyclerView多条目的共性

public interface QuickMultiSupport {    /**     * 获取多条目View类型的数量     */    int getViewTypeCount();    /**     * 根据数据,获取多条目布局ID     */    int getLayoutId(T data);    /**     * 根据数据,获取多条目的ItemViewType     */    int getItemViewType(T data);    /**     * 是否合并条目-->>使用RecyclerView时,如果无效,请用原生的RecyclerView     */    boolean isSpan(T data);

六、打造RecyclerView、ListView、GridView通用的适配器

由于要同时适配RecyclerView、ListView、GridView,也就等于把两个Adapter的实现放在一个类里面
所以代码有点多,但代码我已分开,很容易看。
还有数据都复制出来的,条目的增删改查都在Adapter里面。

/** * RecyclerView、ListView、GridView通用的适配器 */public abstract class QuickAdapter extends BaseAdapter {    private Context mContext;    private List mData;    private int mLayoutId;    private QuickMultiSupport mSupport;    private boolean isRecycler;    private int mPosition;    public QuickAdapter(Context context, List data, int layoutId) {        this.mContext = context;        this.mData = data == null ? new ArrayList() : new ArrayList(data);        this.mLayoutId = layoutId;    }    public QuickAdapter(Context context, List data, QuickMultiSupport support) {        this(context, data, 0);        this.mSupport = support;    }    @Override    public int getCount() {        return mData.size();    }    @Override    public T getItem(int position) {        return mData.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        QuickViewHolder holder;        if (convertView == null) {            int layoutId = mLayoutId;            // 多条目的            if (mSupport != null) {                layoutId = mSupport.getLayoutId(mData.get(position));            }            // 创建ViewHolder            holder = createListHolder(parent, layoutId);        } else {            holder = (QuickViewHolder) convertView.getTag();            // 防止失误,还要判断            if (mSupport != null) {                int layoutId = mSupport.getLayoutId(mData.get(position));                // 如果布局ID不一样,又重新创建                if (layoutId != holder.getLayoutId()) {                    // 创建ViewHolder                    holder = createListHolder(parent, layoutId);                }            }        }        // 绑定View的数据        convert(holder, mData.get(position), position);        return holder.itemView;    }    /**     * 创建ListView的Holer     */    @NonNull    private QuickViewHolder createListHolder(ViewGroup parent, int layoutId) {        QuickViewHolder holder;        View itemView = LayoutInflater.from(mContext).inflate(layoutId, parent, false);        holder = new QuickViewHolder(itemView, layoutId);        itemView.setTag(holder);        return holder;    }    /**     * ViewType的数量     */    @Override    public int getViewTypeCount() {        // 多条目的        if (mSupport != null) {            return mSupport.getViewTypeCount() + super.getViewTypeCount();        }        return super.getViewTypeCount();    }    /**     * 这个方法是共用的     */    @Override    public int getItemViewType(int position) {        mPosition = position;        // 多条目的        if (mSupport != null) {            return mSupport.getItemViewType(mData.get(position));        }        return super.getItemViewType(position);    }    // RecyclerView=================================================================================    @Override    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        isRecycler = true;        // 如果是多条目,viewType就是布局ID        View view;        if (mSupport != null) {            int layoutId = mSupport.getLayoutId(mData.get(mPosition));            view = LayoutInflater.from(mContext).inflate(layoutId, parent, false);        } else {            view = LayoutInflater.from(mContext).inflate(mLayoutId, parent, false);        }        QuickViewHolder holder = new QuickViewHolder(view);        return holder;    }    @Override    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {        if (holder instanceof QuickViewHolder) {            convert((QuickViewHolder) holder, mData.get(position), position);        }    }    @Override    public int getItemCount() {        return mData.size();    }    @Override    public void onAttachedToRecyclerView(RecyclerView recyclerView) {        if (mSupport == null || recyclerView == null) {            return;        }        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();        if (layoutManager instanceof GridLayoutManager) {            final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;            final GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();            // 如果设置合并单元格就占用SpanCount那个多个位置            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {                @Override                public int getSpanSize(int position) {                    if (mSupport.isSpan(mData.get(position))) {                        return gridLayoutManager.getSpanCount();                    } else if (spanSizeLookup != null) {                        return spanSizeLookup.getSpanSize(position);                    }                    return 1;                }            });            gridLayoutManager.setSpanCount(gridLayoutManager.getSpanCount());        }    }    @Override    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {        if (mSupport == null) {            return;        }        int position = holder.getLayoutPosition();        // 如果设置合并单元格        if (mSupport.isSpan(mData.get(position))) {            ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();            if (lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams) {                StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;                p.setFullSpan(true);            }        }    }    // RecyclerView=================================================================================    /**     * 绑定View的数据     */    protected abstract void convert(QuickViewHolder holder, T item, int position);    //==========================================数据相关================================================    public void add(T elem) {        mData.add(elem);        notifyData();    }    public void addAll(List data) {        mData.addAll(data);        notifyData();    }        public void addFirst(T elem) {        mData.add(0, elem);        notifyData();    }        public void set(T oldElem, T newElem) {        set(mData.indexOf(oldElem), newElem);        notifyData();    }        public void set(int index, T elem) {        mData.set(index, elem);        notify();    }    public void remove(T elem) {        mData.remove(elem);        notifyData();    }    public void remove(int index) {        mData.remove(index);        notifyData();    }    public void replaceAll(List elem) {        mData.clear();        mData.addAll(elem);        notifyData();    }    /**     * 清除     */    public void clear() {        mData.clear();        notifyData();    }    private void notifyData() {        if (isRecycler) {            notifyDataSetChanged();        } else {            notifyListDataSetChanged();        }    }    public List getData() {        return mData;    }}

七、通用ViewHolder的抽取

ViewHolder最主要就是实现平时常用的方法,比如:点击事件、长按事件、给TextView设置内容等等
如果不够,实际开发可以自己添加。

public class QuickViewHolder extends RecyclerView.ViewHolder {    private SparseArray> mViews;    private int mLayoutId;    public QuickViewHolder(View itemView) {        this(itemView, -1);    }    public QuickViewHolder(View itemView, int layoutId) {        super(itemView);        mViews = new SparseArray<>();        this.mLayoutId = layoutId;    }    public int getLayoutId() {        return mLayoutId;    }    /**     * 设置条目的点击事件     */    public QuickViewHolder setOnClickListener(View.OnClickListener listener) {        itemView.setOnClickListener(listener);        return this;    }    /**     * 设置条目的长按事件     */    public QuickViewHolder setOnLongClickListener(View.OnLongClickListener listener) {        itemView.setOnLongClickListener(listener);        return this;    }    /**     * 设置View的点击事件     *     * @return     */    public QuickViewHolder setOnClickListener(int viewId, View.OnClickListener listener) {        View view = getView(viewId);        if (view != null) {            view.setOnClickListener(listener);        }        return this;    }    /**     * 获取条目的View     */    public View getView() {        return itemView;    }    /**     * 根据ID获取条目里面的View     */    public  T getView(int viewId) {        WeakReference viewWeakReference = mViews.get(viewId);        View view = null;        if (viewWeakReference == null) {            view = itemView.findViewById(viewId);            if (view != null) {                mViews.put(viewId, new WeakReference<>(view));            }        } else {            view = viewWeakReference.get();        }        return (T) view;    }    public QuickViewHolder setText(int viewId, CharSequence text) {        TextView tv = getView(viewId);        if (tv != null && !TextUtils.isEmpty(text)) {            tv.setText(text);        }        return this;    }    /**     * 设置图片背景颜色     */    public QuickViewHolder setTextColor(int viewId, int color) {        TextView view = getView(viewId);        if (view != null) {            view.setTextColor(color);        }        return this;    }    /**     * 设置控件是否可见     */    public QuickViewHolder setVisible(int viewId, int visible) {        View view = getView(viewId);        view.setVisibility(visible);        return this;    }    /**     * 设置控件选中     */    public QuickViewHolder setChecked(int viewId, boolean checked) {        Checkable view = getView(viewId);        view.setChecked(checked);        return this;    }    /**     * 设置控件背景     */    public QuickViewHolder setBackgroundRes(int viewId, int backgroundRes) {        View view = getView(viewId);        view.setBackgroundResource(backgroundRes);        return this;    }    /**     * 设置图片     */    public QuickViewHolder setImageResource(int viewId, int imageResId) {        ImageView imageView = getView(viewId);        imageView.setImageResource(imageResId);        return this;    }    /**     * 设置图片     */    public QuickViewHolder setImageBitmap(int viewId, Bitmap bitmap) {        ImageView imageView = getView(viewId);        imageView.setImageBitmap(bitmap);        return this;    }}

八、项目实际使用

我只写了多条目的测试使用,对于一种类型的写法更为简单,我就不写了。

public class MainActivity extends AppCompatActivity {    private List mData = new ArrayList<>();    private QuickMultiSupport mQuickSupport;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initData();        initViews();    }    /**     * 多条目的ViewType     */    public interface IViewType {        int getItemViewType();    }    private void initData() {        for (int i = 0; i < 199; i++) {            if (i % 10 == 0) {                MultiBean bean = new MultiBean();                bean.name = "mData--------" + i;                mData.add(bean);            } else {                MultiBean1 bean = new MultiBean1();                bean.name = "mData--------" + i;                mData.add(bean);            }        }        // 多条目支持        mQuickSupport = new QuickMultiSupport() {            // 条目总共两种类型            @Override            public int getViewTypeCount() {                return 2;            }            // 根据不用的JavaBean返回不同的布局            @Override            public int getLayoutId(IViewType data) {                if (data instanceof MultiBean) {                    return R.layout.item_list1;                }                return R.layout.item_list;            }            @Override            public int getItemViewType(IViewType data) {                return data.getItemViewType();            }            @Override            public boolean isSpan(IViewType data) {                // 是否占用一个条目,针对RecyclerView                if (data instanceof MultiBean) {                    return true;                }                return false;            }        };    }    private void initViews() {        ListView listView = findViewById(R.id.list_view);        RecyclerView recyclerView = findViewById(R.id.recycler_view);        // ListView设置Adapter        listView.setAdapter(new CommAdapter(this, mData, mQuickSupport));        // RecyclerView设置Adapter        recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));        recyclerView.setAdapter(new CommAdapter(this, mData, mQuickSupport));    }    class CommAdapter extends QuickAdapter {        public CommAdapter(Context context, List data, int layoutId) {            super(context, data, layoutId);        }        public CommAdapter(Context context, List data, QuickMultiSupport support) {            super(context, data, support);        }        @Override        protected void convert(QuickViewHolder holder, IViewType item, final int position) {            holder.setText(R.id.tv, item.toString());            holder.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    // 点击移除当前条目                    remove(position);                }            });        }    }}

至此无论是RecyclerView还是ListView终于只用一个Adapter,

Demo下载

 

                                                                                                                                                                          -END

更多相关文章

  1. TabLayout的使用及使用中的问题总结
  2. Android(安卓)开发知识点总结
  3. Android学习笔记——常用的基本UI组件及其常用属性值和相关方法
  4. 安卓Doubango架构的使用小结
  5. android 自定义radiobutton的样式 实现自己想要的样子
  6. 关于Android工程compilesdk,minsdk,targetsdk
  7. Android(安卓)Studio配置javah自动生成头文件
  8. Android中自定义Adapter的基本原理
  9. 解决listview设置背景图片以后,拖动出现黑色的问题。

随机推荐

  1. Android魔术(第五弹)—— 一步步实现滑动折
  2. Android输入设备处理流程
  3. Android(安卓)Oss上传文件简单使用
  4. Android 多级菜单联动操作
  5. Android: NullPointerException when usi
  6. 详解Android中fragment和viewpager的那点
  7. 一步一步学Android ROM开发(一)——修改现
  8. ubuntu 下的android环境部署
  9. Android如何通过降低App的Crash提升留存
  10. Android ORMLite数据库简介