android学习-Adapter适配器进阶
参考资源
Android 快速开发系列 打造万能的ListView GridView 适配器
实现代码复用,争取打机**的时间。
android4.4源码 target=android-19
一般自定义Adapter步骤
- 继承BaseAdapter类
- 重写抽象方法(重点是getView方法)
getView方法里面实现步骤
- 加载layout布局或者java代码定义一个view布局
- 获取View对象
- 为View对象设置相关属性
- 返回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适配器进阶的更多相关文章
- Android学习总结——适配器
适配器是AdapterView视图(如ListView - 列表视图控件.Gallery - 缩略图浏览器控件.GridView - 网格控件.Spinner - 下拉列表控件.AutoComplet ...
- Android学习之适配器ArrayAdapter SimpleAdapter
Adapter是个什么角色呢?其实它的作用就是View界面和数据之间的桥梁.我们可以看作是界面数据绑定的一种理解,它所操纵的数据一般都是一些比较复杂的数据,如数组,链表,数据库,集合等. 常用的适配器 ...
- android中Adapter适配器的讲解
Adapter(适配器的讲解) 适配器就我自己来看,我觉得这是一个非常重要的知识点,Adapter是用来帮助填出数据的中间桥梁,简单点说吧:将各种数据以合适的形式显示在View中给用户看.Adapte ...
- Android学习之适配器SimpleCursorAdapter
三. SimpleCursorAdapter与SimpleAdapter用法相近.只是将List对象换成了Cursor对象.而且SimpleCursorAdapter类构造方法的第四个参数from ...
- Android中ListView 控件与 Adapter 适配器如何使用?
一个android应用的成功与否,其界面设计至关重要.为了更好的进行android ui设计,我们常常需要借助一些控件和适配器.今天小编在android培训网站上搜罗了一些有关ListView 控件与 ...
- Android学习总结(十一)———— Adapter的使用
一.Adapter的基本概念 UI控件都是跟Adapter(适配器)打交道的,了解并学会使用这个Adapter很重要, Adapter是用来帮助填充数据的中间桥梁,简单点说就是:将各种数据以合适的形式 ...
- Android学习笔记进阶之在图片上涂鸦(能清屏)
Android学习笔记进阶之在图片上涂鸦(能清屏) 2013-11-19 10:52 117人阅读 评论(0) 收藏 举报 HandWritingActivity.java package xiaos ...
- Android学习笔记-Adapter基础讲解
本节引言 从本节开始我们要讲的UI控件都是跟Adapter(适配器)打交道的,了解并学会使用这个Adapter很重要, Adapter是用来帮助填充数据的中间桥梁,简单点说就是:将各种数据以合适的形式 ...
- 【转】 Pro Android学习笔记(二二):用户界面和控制(10):自定义Adapter
目录(?)[-] 设计Adapter的布局 代码部分 Activity的代码 MyAdapter的代码数据源和构造函数 MyAdapter的代码实现自定义的adapter MyAdapter的代码继续 ...
随机推荐
- (并查集)Is It A Tree? --POJ--1308
链接: http://poj.org/problem?id=1308 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82830#probl ...
- C++ 11可变参数接口设计在模板编程中应用的一点点总结
概述 本人对模板编程的应用并非很深,若要用一句话总结我个人对模板编程的理解,我想说的是:模板编程是对类定义的弱化. 如何理解“类定义的弱化”? 一个完整的类有如下几部分组成: 类的名称: 类的成员变量 ...
- web api解决序列化后返回标准时间带T问题
添加类: public class JsonDataTimeConverter:IsoDateTimeConverter { public JsonDataTimeConvert ...
- PHP编译安装完成之后没有'php.ini'文件的处理方法
在我们编译安装PHP的时候,编译安装完成是不会自动生成php.ini文件的,所以需要我们手动生成. 1.通过命令行确定php.ini文件的位置 php -r "phpinfo();" ...
- mysql的sql性能分析器
MySQL 的SQL性能分析器主要用途是显示SQL执行的整个过程中各项资源的使用情况.分析器可以更好的展示出不良SQL的性能问题所在. mysql sql profile的使用方法 1.开启mysql ...
- [Ubuntu]管理开机启动项的软件
sudo apt-get install sysv-rc-conf
- 国内云计算的缺失环节: GPU并行计算(转)
[IT时代周刊编者按]云计算特有的优点和巨大的商业前景,让其成为了近年来的IT界最热门词汇之一.当然,这也与中国移动互联网的繁荣紧密相关,它们需要有相应的云计算服务作为支撑.但本文作者祁海江结合自身的 ...
- c#实现AOP
AOP:面向切面编程,通过预编译方式或运行期动态代理实现程序功能的中统一处理业务逻辑的一种技术,比较常见的场景是:日志记录,错误捕获.性能监控等 AOP详解:https://www.cnblogs.c ...
- Restful认识和 IK分词器的使用
什么是Restful风格 Restful是一种面向资源的架构风格,可以简单理解为:使用URL定位资源,用HTTP动词(GET,POST,DELETE,PUT)描述操作. 使用Restful的好处: 透 ...
- jzoj5879. 【NOIP2018提高组模拟9.22】电路图 B
tj:一道好題 看區間操作可以想到線段樹 並聯操作公式:a1∗a2/(a1+a2)a1*a2/(a1+a2)a1∗a2/(a1+a2) 串聯操作公式:a1+a2a1+a2a1+a2 我們發現,一個區間 ...