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的代码继续 ...
随机推荐
- 201521123035-个人作业4——alpha阶段个人总结
个人总结 在alpha 结束之后, 每位同学写一篇个人博客, 总结自己的alpha 过程: 第一部分 类别 具体技能和面试问题 现在的回答(大三) 语言 最拿手的计算机语言是一?,代码量多少?(偏前端 ...
- hdu 2190 悼念512汶川大地震遇难同胞——重建希望小学
题目 这道题拿到的时候拼凑了一会,感觉挺难的,然后博客说是:递推,我觉得递推其实就是找规律. 这是别人的思路:对于n米的长度,可以是由n-1长度加1而来,对于增加的1,只有三块1*1的砖一种铺法: 还 ...
- spring boot搭建Hello Word
一.安装与配置jdk 二.安装与配置maven 安装好maven,必须配置环境变量 通过cmd命令查询maven是否安装成功,以下是安装成功的界面 修改setting.xml的配置,制定本地仓库的路径 ...
- 团队项目(第三周)—GG队
需求改进&系统设计 队员 学号 叶尚文(队长) 3116008802 蔡晓晴 3216008808 杜婷萱 3216008809 龙剑初 3116004647 于泽浩 3116004661 一 ...
- Elasticsearch 的一些关键概念
我更喜欢把 Elasticsearch 作为一种 nosql 去理解,它的一些开发概念和 MongoDB 以及 Redis 没有太大的区别,不过了解 Elasticsearch 中的一些核心概念对于你 ...
- DropDownList切换选择,服务器控件Repeater未更新
将EnableViewState属性设置为false,这样禁止服务器控件使用视图状态,也就是禁止发送给浏览器HEML中的缓存副本, 每次都会使用新数据. 一旦页面的控件很多,频繁的传递控件状态值对网络 ...
- (C#)字符串反转
方法一: public static string Reverse(string name) { if (String.IsNullOrEmpty(name)) { ...
- Stm32 ADC学习
stm32 ADC 简介 stm32的ADC是 12位逐次逼近型 模拟数字转换器;它包括18个通道,可以用来测量16个外部通道和2个内部通道.ADC转换的结果存放在16位数据寄存器(ADC规则数据寄存 ...
- C++实现排序算法
稳定性:快速 希尔 选择 堆排序不稳定 时间复杂度:平均情况下,快速.希尔.归并和堆排序的时间复杂度均为O(nlog2(n)),其他都是O(n^2).最坏情况下,快排的时间复杂度为O(n^2) #in ...
- .NET Core中使用Dapper操作Oracle存储过程最佳实践
为什么说是最佳实践呢?因为在实际开发中踩坑了,而且发现网上大多数文章给出的解决方法都不能很好地解决问题.尤其是在获取类型为OracleDbType.RefCursor,输出为:ParameterDir ...