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的代码继续 ...
随机推荐
- (匹配 二维建图) Antenna Placement --POJ --3020
链接: http://poj.org/problem?id=3020 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82834#probl ...
- volatile 类型修饰符
volatile 类型修饰符 1.解释 就像大家更熟悉的const一样,volatile是一个类型修饰符(type specifier).它是被设计用来修饰被不同线程访问和修改的变量.如果不加入vol ...
- Oracle EBS 常用网站列表
http://www.lifandong.com/erp/356 Oracle EBS 常用网站列表 英文站: Oracle EBS R12 官方参考手册(User Guide, Implementa ...
- ASP.NET 中 <%= %> 与 <%: %> 的区别
做个备忘 <%= %> 内容原封不动输出 <%: %> 对内容进行编码后输出 即:<%: str %> 等价于 <%= Html.Encode(str) %& ...
- SQL笔记---多表左联
这是实际场景当中的一个例子,拿出来分析总结思路. -- SQL 查询 --SELECT orderQuery.Rk_SkuCode , orderQuery.SkuName, ...
- Struts2-057/CVE-2018-11776两个版本RCE漏洞分析(含EXP)
0x01 前言 2018年8月22日,Apache Strust2发布最新安全公告,Apache Struts2存在远程代码执行的高危漏洞(S2-057/CVE-2018-11776),该漏洞由Sem ...
- Linux(Debian)网卡设置
debian IP地址配置 vim /etc/network/interface 配置网卡eth0的IP地址 auto eth0 表示网卡随系统自动请 iface eth0 inet static ...
- 先装VS2008之后,又装了2013,然后启动VS2008提示“Tools Version”有问题?
这个网上资料一搜很多,我就是按照下面这个链接去解决的,删除 “14.0” 整个键值文件夹之后重启VS2008就好了, 注意:上面第一张图是我在网上找的08和10版本弹出的错误,我自己弹出的是提示14. ...
- 《JavaScript高级程序设计》5.5 Function类型
5.5 Function类型 函数实质上是对象, 每个函数都是Function类型的实例, 并且都和其他引用类型一样具有属性和方法. 因此函数名实际上也是一个指向函数对象的指针, 不会与某个函数绑定. ...
- Delphi - 让Delphi10.2在Windows下开发的图形界面程序运行在64位Linux中!
FmxLinux官网:https://fmxlinux.com/ 参考: http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Linux_Applica ...