参考资源

Android 快速开发系列 打造万能的ListView GridView 适配器

实现代码复用,争取打机**的时间。

android4.4源码 target=android-19

一般自定义Adapter步骤

  • 继承BaseAdapter类
  • 重写抽象方法(重点是getView方法)

getView方法里面实现步骤

  1. 加载layout布局或者java代码定义一个view布局
  2. 获取View对象
  3. 为View对象设置相关属性
  4. 返回convertView

最低级,为每一个ListView或GridView编写一个专有Adapter

public class SensorAdapter extends BaseAdapter {
Context context;
List<Sensor> mData;
public SensorAdapter(Context context,List<Sensor> mData) {
this.context=context;
this.mData=mData;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return mData.size();
} @Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return mData.get(position);
} @Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
} public View getView(int position, View convertView, ViewGroup parent)
{
convertView = LayoutInflater.from(context).inflate(R.layout.list_item, parent,
false);
TextView mTextView=(TextView) convertView.findViewById(R.id.list_item);
mTextView.setText(mData.get(position).getName());
return convertView;
}
}

上面getView()方法内没有进行优化,是我一开始认识BaseAdapter写了。

稍微优化下getView()方法

public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder viewHolder = null;
if (convertView == null)
{
convertView = LayoutInflater.from(context).inflate(R.layout.list_item, parent,
false);
viewHolder = new ViewHolder();
viewHolder.mTextView = (TextView) convertView
.findViewById(R.id.list_item);
convertView.setTag(viewHolder);
} else
{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.mTextView.setText(mData.get(position).getName());
return convertView;
} private final class ViewHolder
{
TextView mTextView;
}

每次调用getView()减少内存使用,当convertView!=null时。将内部类ViewHolder作为convertView的Tag缓存需要放在ListView中的View数组。

为每个listview或gridview都自定义一个adapter,那么10个listview就需要10个自定义的adapter,100个甚至1000个就需要对应数量adapter。这有点恐怖

上网查的下万能适配器,发现一大把,选的鸿洋大神多的万能适配器为模板,写下笔记。

上面用viewholder存放特定的View组件,优化查找所有View并且存放所有Views组件

public class ViewHolder
{
private final SparseArray<View> mViews;
SparseArray类似于Map以键值对的形式作为Views的容器
private View mConvertView; //要通过这个convertView组件进行查找所有View
private ViewHolder(Context context, ViewGroup parent, int layoutId,
int position)
{
this.mViews = new SparseArray<View>();
mConvertView = LayoutInflater.from(context).inflate(layoutId, parent,
false);
//setTag
mConvertView.setTag(this); } /**
* 拿到一个ViewHolder对象
* @param context
* @param convertView
* @param parent
* @param layoutId
* @param position
* @return
*/
public static ViewHolder get(Context context, View convertView,
ViewGroup parent, int layoutId, int position)
{ if (convertView == null)
{
return new ViewHolder(context, parent, layoutId, position);
}
return (ViewHolder) convertView.getTag();
} /**
* 通过控件的Id获取对于的控件,如果没有则加入views
* @param viewId
* @return
*/
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 View getConvertView()
{
return mConvertView;
} }

getView()中使用

 public View getView(int position, View convertView, ViewGroup parent)
{
//实例化一个viewHolder
ViewHolder viewHolder = ViewHolder.get(mContext, convertView, parent,
R.layout.item_single_str, position);
//通过getView获取控件
TextView tv = viewHolder.getView(R.id.id_tv_title);
//使用
tv.setText(mDatas.get(position));
return viewHolder.getConvertView();
}

通过上面优化可以做到只需要一个通用ViewHolder,任意多个Adapter就可以搞定所有项目

通过上面优化发现adapter还不能适用所有情况

1存放数据的List要通用,直接用泛型来代替。2getView()里面中间部分在不同适配器中情况不同,抽取出来实现

这样只需要在new MyAdapter(){...}重写抽象方法进行view组件的设置

最终结果

CommonAdapter.java

 @Override
public View getView(int position, View convertView, ViewGroup parent)
{
final ViewHolder viewHolder = getViewHolder(position, convertView,
parent);
convert(viewHolder, getItem(position));
return viewHolder.getConvertView(); }
/*
* 布局里面的View常用也就那么几种:ImageView,TextView,Button,CheckBox等等
* viewholder中封装常用的方法
*/
public abstract void convert(ViewHolder helper, T item); private ViewHolder getViewHolder(int position, View convertView,
ViewGroup parent)
{
return ViewHolder.get(mContext, convertView, parent, mItemLayoutId,
position);
}

ViewHolder.java

public class ViewHolder
{
private final SparseArray<View> mViews;
private int mPosition;
private View mConvertView;
private Context context;
private ViewHolder(Context context, ViewGroup parent, int layoutId,
int position)
{
this.context=context;
this.mPosition = position;
this.mViews = new SparseArray<View>();
mConvertView = LayoutInflater.from(context).inflate(layoutId, parent,
false);
// setTag
mConvertView.setTag(this);
} /**
* 拿到一个ViewHolder对象
*
* @param context
* @param convertView
* @param parent
* @param layoutId
* @param position
* @return
*/
public static ViewHolder get(Context context, View convertView,
ViewGroup parent, int layoutId, int position)
{
if (convertView == null)
{
return new ViewHolder(context, parent, layoutId, position);
}
return (ViewHolder) convertView.getTag();
} public View getConvertView()
{
return mConvertView;
} /**
* 通过控件的Id获取对于的控件,如果没有则加入views
*
* @param viewId
* @return
*/
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;
} /**
* 为TextView设置字符串
*
* @param viewId
* @param text
* @return
*/
public ViewHolder setText(int viewId, String text)
{
TextView view = getView(viewId);
view.setText(text);
return this;
} /**
* 为ImageView设置图片
*
* @param viewId
* @param drawableId
* @return
*/
public ViewHolder setImageResource(int viewId, int drawableId)
{
ImageView view = getView(viewId);
view.setImageResource(drawableId); return this;
} /**
* 为ImageView设置图片
*
* @param viewId
* @param drawableId
* @return
*/
public ViewHolder setImageBitmap(int viewId, Bitmap bm)
{
ImageView view = getView(viewId);
view.setImageBitmap(bm);
return this;
} /**
* 为ImageView设置图片
*
* @param viewId
* @param drawableId
* @return
*/
/* public ViewHolder setImageByUrl(int viewId, String url)
{
ImageLoader.getInstance(3, Type.LIFO).loadImage(url,
(ImageView) getView(viewId));
return this;
} */ public ViewHolder setImageByUrl(int viewId,String url){
Picasso.with(context).load(url).into((ImageView) getView(viewId));
// ImageLoader.getInstance().init(ImageLoaderConfiguration.createDefault(context));
// ImageLoader.getInstance().displayImage(url, (ImageView) getView(viewId));
return this;
}
public int getPosition()
{
return mPosition;
} }

MainActivity.java

mAdapter = new CommonAdapter<String>(getApplicationContext(),
R.layout.item_single_str, mDatas)
{
@Override
protected void convert(ViewHolder viewHolder, String item)
{
viewHolder.setText(R.id.id_tv_title, item);
}
};

到这里万能适配器就写完了。

ps:说下ListView中getView()方法被多次调用的情况吧!

查看下网上资料和源码,发现getView是在AbsListView.obtainView()中被调用。

obtainView()会在ListView中被调用

obtainView()调用的次数

前两个是用来测量listView大小

heightMode == MeasureSpec.UNSPECIFIED调用1次

heightMode == MeasureSpec.AT_MOST调用1次加后面3次共4次。有些人调式是发现getView被调用4次,有些人3次。有点迷惑

onMeasure(int widthMeasureSpec, int heightMeasureSpec)
1次
measureHeightOfChildren(int widthMeasureSpec, int startPosition, int endPosition,
final int maxHeight, int disallowPartialChildPosition)
1次
makeAndAddView(int position, int y, boolean flow, int childrenLeft,
boolean selected)
1次
addViewAbove(View theView, int position)
1次
addViewBelow(View theView, int position)
1次

android学习-Adapter适配器进阶的更多相关文章

  1. Android学习总结——适配器

    适配器是AdapterView视图(如ListView - 列表视图控件.Gallery - 缩略图浏览器控件.GridView - 网格控件.Spinner - 下拉列表控件.AutoComplet ...

  2. Android学习之适配器ArrayAdapter SimpleAdapter

    Adapter是个什么角色呢?其实它的作用就是View界面和数据之间的桥梁.我们可以看作是界面数据绑定的一种理解,它所操纵的数据一般都是一些比较复杂的数据,如数组,链表,数据库,集合等. 常用的适配器 ...

  3. android中Adapter适配器的讲解

    Adapter(适配器的讲解) 适配器就我自己来看,我觉得这是一个非常重要的知识点,Adapter是用来帮助填出数据的中间桥梁,简单点说吧:将各种数据以合适的形式显示在View中给用户看.Adapte ...

  4. Android学习之适配器SimpleCursorAdapter

    三.   SimpleCursorAdapter与SimpleAdapter用法相近.只是将List对象换成了Cursor对象.而且SimpleCursorAdapter类构造方法的第四个参数from ...

  5. Android中ListView 控件与 Adapter 适配器如何使用?

    一个android应用的成功与否,其界面设计至关重要.为了更好的进行android ui设计,我们常常需要借助一些控件和适配器.今天小编在android培训网站上搜罗了一些有关ListView 控件与 ...

  6. Android学习总结(十一)———— Adapter的使用

    一.Adapter的基本概念 UI控件都是跟Adapter(适配器)打交道的,了解并学会使用这个Adapter很重要, Adapter是用来帮助填充数据的中间桥梁,简单点说就是:将各种数据以合适的形式 ...

  7. Android学习笔记进阶之在图片上涂鸦(能清屏)

    Android学习笔记进阶之在图片上涂鸦(能清屏) 2013-11-19 10:52 117人阅读 评论(0) 收藏 举报 HandWritingActivity.java package xiaos ...

  8. Android学习笔记-Adapter基础讲解

    本节引言 从本节开始我们要讲的UI控件都是跟Adapter(适配器)打交道的,了解并学会使用这个Adapter很重要, Adapter是用来帮助填充数据的中间桥梁,简单点说就是:将各种数据以合适的形式 ...

  9. 【转】 Pro Android学习笔记(二二):用户界面和控制(10):自定义Adapter

    目录(?)[-] 设计Adapter的布局 代码部分 Activity的代码 MyAdapter的代码数据源和构造函数 MyAdapter的代码实现自定义的adapter MyAdapter的代码继续 ...

随机推荐

  1. (线段树模板)A Simple Problem with Integers --POJ--3468

    链接: http://poj.org/problem?id=3468 代码: #include<stdio.h> #include<algorithm> #include< ...

  2. HDU6023 Automatic Judge 2017-05-07 18:30 73人阅读 评论(0) 收藏

    Automatic Judge Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  3. 团队博客-第三周:需求改进&系统设计(科利尔拉弗队)

    针对课堂讨论环节老师和其他组的问题及建议,对修改选题及需求进行修改 需求规格说明书: 1.打开网页,弹出询问时候创建账号.是:分配数字组成账号,用户填写密码,确定登录进入首页:否,用已有账号登录(传参 ...

  4. [redis] redis 如何删除匹配模式的多个key值

    redis-cli keys "user:*" | grep "user:[0-9]\+$" | xargs redis-cli DEL redis-cli k ...

  5. XCode 7.3.1(dmg) 官方直接下载地址(离线下载)

    XCode 7 7.3.1:https://developer.apple.com/services-account/download?path=/Developer_Tools/Xcode_7.3. ...

  6. 配置Jenkins构建失败触发邮件报警机制

    系统管理 1.进入系统管理-->系统设置 定位到Jenkins Location配置项   配置系统管理员邮件地址 系统管理员邮件地址需要同发送报警邮件地址相同 定位到邮件通知   配置SMTP ...

  7. HTTP的瓶颈

    http协议,1.0或1.1版本,一个连接智能发送一个请求,通信都是基于请求/响应方式的,请求只能从客户端发起(半双工),发送冗长的首部. 在交互比较频繁的社交网站等,一直轮训带来的网络及服务器压力是 ...

  8. C# 控件绘制

    绘制方法: 1.在控件的paint事件中绘制 2.绘制成图片,然后作为背景图或图片贴到工作区. Bitmap bmp = new Bitmap(IWidth, this.Height); Graphi ...

  9. 【cocos2d-x 手游研发----怪物智能AI】

    原创文章,转载请注明出处:http://www.cnblogs.com/zisou/p/cocos2d-xARPG4.html 谈到怪物AI,我觉得就比较话多了,首先理解一下(Artificial I ...

  10. 926. Flip String to Monotone Increasing

    A string of '0's and '1's is monotone increasing if it consists of some number of '0's (possibly 0), ...