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的代码继续 ...
随机推荐
- 学习Spring Data JPA
简介 Spring Data 是spring的一个子项目,在官网上是这样解释的: Spring Data 是为数据访问提供一种熟悉且一致的基于Spring的编程模型,同时仍然保留底层数据存储的特殊 ...
- linux系统编程之文件与IO(一):文件描述符、open,close
什么是IO? 输入/输出是主存和外部设备之间拷贝数据的过程 设备->内存(输入操作) 内存->设备(输出操作) 高级I/O ANSI C提供的标准I/O库称为高级I/O,通常也称为带缓冲的 ...
- echarts呈现数据表图形
讲一下echarts的用法,列举了两个图表,一个是单柱图,一个是多柱图,至于饼状图,只许更改echarts的类型就好了 一.首先是要两个div,用来存放两个图表 <div class=" ...
- 如何做好iOS应用安全?这有一把行之有效的“三板斧”
本文由 网易云发布. iOS应用面临很多破解问题,常见的有IAP内购破解.山寨版本.破解版本等:大众应用上,微信抢红包.微信多开等:而在iOS游戏上,越来越泛滥的外挂问题也不断困扰着游戏厂商. 网易 ...
- Day 26封装
一.封装 广义上的封装: 属于一个类的静态和动态属性,总是出现在一个类中. 使用的永远用类名或者对象名调用. 狭义上的封装:就是把变量和方法私有化,在类的外部以及子类中不能直接使用了 . class ...
- 20164317《网络对抗技术》Exp3 免杀原理与实践
一.实验要求 1.1 正确使用msf编码器(0.5分),msfvenom生成如jar之类的其他文件(0.5分),veil-evasion(0.5分),加壳工具(0.5分),使用shellcode编程( ...
- http 缓存策略浅析
从一道经典的面试题说起 "用户输入 URL 到浏览器显示页面,这个过程发生了什么?",作为前端开发,这个题目相信大家并不陌生.楼主的答案分为两部: 一.网络通信 应用层 DNS 域 ...
- QT for Android记录
1.<Qt on Android核心编程> blog: http://blog.csdn.net/foruok/article/details/38510195
- 实现可搜索仿select下拉选中
由于在优化项目中,发现先前写的一个活化石级的的可搜索下拉功能在高速搜索中会出现卡顿现象 1.起初的解决方法是在搜索事件中加入防抖函数隔一段时间才去触发他,同时搜索的不再是html文档片段,而是直接对数 ...
- 【xsy3423】党² 线段树+李超线段树or动态半平面交
本来并不打算出原创题的,此题集CF542A和sk的灵感而成,算个半原创吧. 题目大意: 给定有$n$个元素的集合$P$,其中第$i$个元素中包含$L_i,R_i,V_i$三个值. 给定另一个有$n$个 ...