自定义通用Adapter适配ListView GridView
来源:互联网 发布:windows 调试模式 编辑:程序博客网 时间:2024/06/07 14:59
概述
相信做Android开发的写得最多的就是ListView,GridView的适配器吧,对于Adapter一般都继承BaseAdapter复写几个方法,getView里面使用ViewHolder模式,其实大部分的代码基本都是类似的。
网上也有一些自定义Adapter的封装,本篇博客的Adapter的可以适应于多种类型的layout,也就是实现对话效果,而且代码和类设计都比较简单。
效果图,其中图片和文字是两个不同的layout:
类设计图
从上面的类图我们可以看到,直接继承BaseAdapter是类MutiplyCommonAdapter,根据类名就知道,这个类可以实现多种不同的布局。
我们把只能实现一种布局看成是该类的特殊情况,继承并且新建了类CommonAdapter。这个类是我们最常使用到的类。
至于ViewHolder是一个辅助类,在常见的getView()方法中,我们总是设置一个ViewHolder来进行缓存,这里也是做了这个工作,并且提供了一些快捷设置的方法,例如根据id设置文本,背景等,减少了我们使用findViewById()的次数。
MutiplyCommonAdapter
public abstract class MutiplyCommonAdapter<T> extends BaseAdapter{ protected Context mContext; protected List<T> mDatas; private int[] layoutId; public MutiplyCommonAdapter(Context context, List<T> datas, int... layoutId){ this.mContext = context; this.mDatas = datas; this.layoutId = layoutId; } @Override public int getCount(){ return mDatas.size(); } @Override public T getItem(int position){ return mDatas.get(position); } @Override public long getItemId(int position){ return position; } @Override public int getViewTypeCount() { return layoutId.length; } @Override public abstract int getItemViewType(int position); @Override public View getView(int position, View convertView, ViewGroup parent){ ViewHolder holder = ViewHolder.get(mContext, convertView, parent, layoutId[getItemViewType(position)], position); convert(holder, getItem(position),getItemViewType(position)); return holder.getConvertView(); } //type是getItemViewType(position)的返回值 public abstract void convert(ViewHolder holder, T t,int type);}
观察上面的类,构造方法的最后传入了一个int[]类型的layout数组,根据layout数组的长度,我们就可以得到getViewTypeCount()的返回值。
另外getItemViewType(int position)需要使用者自己定义,因为实现根据需求各有不同,例如我们根据奇偶行实现不同的布局。
接下来最主要的一个方法就是getView()方法,里面使用了ViewHolder这个辅助类返回了ViewHolder,这样我们就不需要自己实现Viewholder了。
最后是convert()方法,这里是我们自己对控件进行操作的地方。
CommonAdapter
public abstract class CommonAdapter<T> extends MutiplyCommonAdapter<T>{ private CommonAdapter(Context context, List<T> datas, int... layoutId) { super(context, datas, layoutId); } public CommonAdapter(Context context, List<T> datas, int layoutId) { this(context, datas, new int[]{layoutId}); } @Override public int getItemViewType(int position) { return 0; } public abstract void convert(ViewHolder holder, T t); @Override public void convert(ViewHolder holder, T t,int type){ convert(holder,t); }}
CommonAdapter目的是提供单一布局的Adapter。
显然getItemViewType(int position)返回0;
convert(ViewHolder holder, T t)不需要再传入layout类型了,因为只有一种类型。
ViewHolder
public class ViewHolder { /** 控件引用缓存 */ private final SparseArray<View> mViews; private final Context mContext; private int mPosition; private View mConvertView; public ViewHolder(Context context, ViewGroup parent, int layoutId,int position){ mContext = context; mPosition = position; mViews = new SparseArray<View>(); mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false); mConvertView.setTag(this); } public static ViewHolder get(Context context, View convertView, ViewGroup parent, int layoutId, int position){ if (convertView == null) return new ViewHolder(context, parent, layoutId, position); ViewHolder holder = (ViewHolder) convertView.getTag(); holder.mPosition = position; return holder; } /** * 根据id获取控件 * @param viewId * @return */ @SuppressWarnings("unchecked") public <T extends View> T getView(int viewId){ View view = mViews.get(viewId); if (view == null){ view = mConvertView.findViewById(viewId); mViews.put(viewId, view); } return (T) view; } public ViewHolder setText(int viewId, String value) { TextView view = getView(viewId); view.setText(value); return this; } ...}
首先构造函数中,使用LayoutInflater根据layoutId创建了布局View,并且将当期ViewHolder设置View的Tag。
然后是get()方法里面,判断View是否被缓存,如果是直接返回,否则根据Tag获取。
另外提供了一个getView()方法用于方便使用者用过id获取控件对象。其实这个类里面有很多这种工具方法,没有一一贴出来,典型的就是setText(int viewId, String value)方法。
简单使用
创建一个MyAdapter来根据position实现两种布局
public class MyAdapter extends MutiplyCommonAdapter<String>{ public MyAdapter(Context context, List<String> datas, int... layoutId) { super(context, datas, layoutId); } //volley public RequestQueue requestQueue = Volley.newRequestQueue(mContext); public CombineCache mCombineCache = new CombineCache(mContext); public ImageLoader mImageLoader = new ImageLoader(requestQueue, mCombineCache); @Override public int getItemViewType(int position) { return position%2;//根据奇偶行设置不同的布局 } @Override public void convert(final ViewHolder holder, String url, int type) { switch (type) { case 0: loadImg(holder,url); break; case 1: loadText(holder,url); break; default: break; } } //图片布局 private void loadImg(final ViewHolder holder,String url){ mImageLoader.get(url, new ImageListener() { @Override public void onErrorResponse(VolleyError error) { Log.i("cky", "error"); ImageView img = (ImageView)(holder.getView(R.id.img)); img.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_launcher)); } @Override public void onResponse(ImageContainer response, boolean isImmediate) { ImageView img = (ImageView)(holder.getView(R.id.img)); img.setImageBitmap(response.getBitmap()); } },400,400); } //文字布局 private void loadText(final ViewHolder holder,String url){ holder.setText(R.id.text,url); }}
在Activity里面我这样使用
final MyAdapter myAdapter = new MyAdapter(this,arr,R.layout.listview_cell,R.layout.listview_cell2);//arr是图片地址listview.setAdapter(myAdapter);
写在最后
通过对Adapter的简单封装,我们大大减少了自定义Adapter过程中的麻烦。网上实现多布局Adapter的设计,都是以单个布局Adapter为基类,然后提供一个辅助类来实现多布局。
这样的思路显然不直观,单个布局Adapter是多个布局Adapter的一种特殊情况,那么他们的继承关系就很清楚了。
在ViewHolder中,我们并没有实现setImage()之类的为控件设置图片的方法,因为对于图片的加载,有许多不同的策略(例如Volley,UIL等),大家在实际使用的时候,可以根据项目添加这些方法。
源码下载
- 自定义通用Adapter适配ListView GridView
- 自定义通用Adapter适配ListView GridView
- 打造通用Adapter(适用于ListView,GridView)
- 封装一个通用的 listview/gridview Adapter
- Android中适用于ListView、GridView等组件的通用Adapter
- Android中适用于ListView、GridView等组件的通用Adapter
- Android中适用于ListView、GridView等组件的通用Adapter
- 利用butterknife 打造通用adapter 适用listview,gridview
- 通用ListView Adapter
- ListView 通用Adapter封装
- ListView GridView Adapter
- ListView和GridView 自定义Adapter的getView()方法调用问题
- GridView自定义Adapter
- Android GridView自定义Adapter
- listview、gridview通用适配器
- Android中适用于ListView、GridView等组件的通用Adapter (转)
- ListView(二)通用的Adapter
- 通用于ListView的Adapter
- 【Matlab开发】matlab中bar绘图设置与各种距离度量
- HDU 5522 Numbers
- 模拟数字小时钟
- Android开发大神博客汇总
- 让Ecshop网店系统用户自动登陆
- 自定义通用Adapter适配ListView GridView
- DAO层,Service层,Controller层、View层
- 浅拷贝和深拷贝
- init rtl8367
- 通信机制
- c++ explicit
- C标准库(1)
- PS学习笔记(三)——蒙版的使用
- 工作中的log4j