listview中的adapter学习小结
概述
Adapter是数据和UI之间的一个桥梁,在listview,gridview等控件中都会使用到,android给我们提拱了4个adapte供我们使用:
- BaseAdapter是一个抽象类,继承它需要实现较多的方法
- ArrayAdapter支持泛型操作,最为简单,只能展示一行字
- SimpleAdapter有最好的扩充性,可以自定义出各种效果
- SimpleCursorAdapter可以适用于简单的纯文字型ListView,它需要Cursor的字段和UI的id对应起来。如需要实现更复杂的UI也可以重写其他方法。可以认为是SimpleAdapter对数据库的简单结合,可以方便地把数据库的内容以列表的形式展示出来
在实际项目中往往用的最多的还是BaseAdapter,系统提供的几个adapter大多数只有在写demo才为了图省事去用一下而已,这在包建强的《app研发录》中的也有所体现,第一章介绍adapter时就提到要求所有adpater继承自BaseAdapter,从构造函数List<自定义实体>这样的数据集合,从而完成ListView的填充工作,本篇主要总结一下BaseAdapter.
传统的方式
基本的一般只需要4步即可完成
- 继承
BaseAdapter- 实现
getCount、getItem、getItemId、getView- 书写
ViewHolder内部类去存储复用View- 在
getView中实现数据的设置
下面给出一个基本的NormalAdapter实现的代码
public class NormalAdapter extends BaseAdapter {
private LayoutInflater layoutInflater;
private List<TestBean> datas;
//NormalAdapter需要一个Context,通过Context获得Layout.inflater,然后通过inflater加载item的布局
public NormalAdapter(Context context, List<TestBean> datas) {
layoutInflater = LayoutInflater.from(context);
this.datas = datas;
}
@Override
public int getCount() {
return datas.size();
}
@Override
public Object getItem(int position) {
return datas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.item_list, parent, false);
holder = new ViewHolder();
holder.tv_title = (TextView) convertView.findViewById(R.id.tv_title);
holder.tv_des = (TextView) convertView.findViewById(R.id.tv_desc);
holder.tv_time = (TextView) convertView.findViewById(R.id.tv_time);
holder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);
convertView.setTag(holder);
} else {
//说明convertview已经被复用,已经设置过tag
holder = (ViewHolder) convertView.getTag();
}
TestBean testBean = datas.get(position);
holder.tv_title.setText(testBean.getTitle());
holder.tv_des.setText(testBean.getDesc());
holder.tv_time.setText(testBean.getTime());
holder.tv_name.setText(testBean.getName());
return convertView;
}
/**
* viewHoder服务于特定的Adapter,根据对应的item_layout书写
*/
private static class ViewHolder {
TextView tv_title;
TextView tv_des;
TextView tv_time;
TextView tv_name;
}
}
初步封装
这样会带来一些问题,一个listview就要对应一个adpater,还要对应一个viewholder,这里有很多冗余的代码如getCount、getItem、getItemId这些可以被抽象出来,其实封装的思路很简单,主要集中在getView这个方法上,通过分析最普通的NormalAdapter可以看出,getView主要完成三个部分
- 根据convertView是否为空来生成对应的holder
- 根据对应的convertView来设置其控件上的数据
返回convertView
这三部分主要封装在BaseholderTool中BaseAdapterTool
BaseAdapterTool比较简单就是继承BaseAdapter重写几种方法在getView中使用BaseViewHolderTool
关键代码如下
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//使用通用vierholder
BaseViewHolderTool holder = BaseViewHolderTool.get(context, convertView, parent, layoutId, position);
convert(holder, getItem(position));
return holder.getBaseConvertView();
}
/**
* 将该方法公布出去
*
* @param holder
* @param t
*/
public abstract void convert(BaseViewHolderTool holder, T t);
BaseviewHolderTool
用来封装viewHolder,从基本的NormalAdapter可以看出,viewholder就是相当于一个缓存,根据convertView来判断是否重用holder;而convertView就是listview每个item的布局,因此需要完成解析布局的功能,这里采用更加高效的SparseArray
代替hashmap(android推荐);holder又要肩负着获取布局控件的使命因此又要暴露出对应的方法
public class BaseViewHolderTool {
private SparseArray<View> views;
private int basePosition;
private View baseConvertView;
public BaseViewHolderTool(Context context, ViewGroup parent, int layoutId, int position) {
this.basePosition = position;
this.views = new SparseArray<View>();
baseConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
baseConvertView.setTag(this);
}
/**
* 获得convertview不同情况的holder
*
* @param context
* @param convertView
* @param parent
* @param layoutId
* @param position
* @return
*/
public static BaseViewHolderTool get(Context context, View convertView, ViewGroup parent, int layoutId, int position) {
if (convertView == null) {
return new BaseViewHolderTool(context, parent, layoutId, position);
} else {
BaseViewHolderTool holder = (BaseViewHolderTool) convertView.getTag();
holder.basePosition = position;//更新position位置
return holder;
}
}
/**
* 通过id获取控件
*
* @param viewId
* @param <T>
* @return
*/
public <T extends View> T getView(int viewId) {
View view = views.get(viewId);
if (view == null) {
view = baseConvertView.findViewById(viewId);
views.put(viewId, view);
}
return (T) view;
}
public View getBaseConvertView() {
return baseConvertView;
}
}
效果图如下:
多个type的item
这里要谈的是多个布局同时出现在一个listview中,
这时候就需要
重写 getViewTypeCount() – 返回你有多少个不同的布局
重写 getItemViewType(int) – 由position返回view type id
然后在getview中,
int viewType = getItemViewType(position);//获取对应的类型
这里做了一个简单地demo在偶数行显示item_list2,奇数行显示item_list
@Override
public int getItemViewType(int position) {
return position % 2 == 0 ? TYPE_SEPARATOR : TYPE_MAIN;
}
效果图如下
demo已经传到github上AdapterStudy
listview中的adapter学习小结的更多相关文章
- android代码优化----ListView中自定义adapter的封装(ListView的模板写法)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- 42.Android之ListView中ArrayAdapter简单学习
今天学习下Android中ListView关于ArrayAdapter数据绑定, 废话少说直接上代码. 改下布局文件: <?xml version="1.0" encodin ...
- Java中的equals学习小结
Java中的equals是十分重要的,和= =要区别开来,现在小结其主要内容,而且要将 = =和 equals列为重要的对比概念来学习 1.声明格式 public boolean equals ...
- Mongodb中更新的学习小结
今天继续很久没学习的mongodb的简单学习,今天来看的是更新.先来看简单的用法: use updatetest >switched to db updatetest 首先插入一下: db.th ...
- java中继承关系学习小结
继承:把多个类中同样的内容提取出来.定义到一个类中,其它类仅仅须要继承该类.就能够使用该类公开的属性和公开的方法. 继承的优点:提高代码的复用性.提高代码的可维护性.让类与类之间产生关系,是多态存 ...
- ListView中动态显示和隐藏Header&Footer
ListView的模板写法 ListView模板写法的完整代码: android代码优化----ListView中自定义adapter的封装(ListView的模板写法) 以后每写一个ListView ...
- android 自定义adapter和线程结合 + ListView中按钮滑动后状态丢失解决办法
adapter+线程 1.很多时候自定义adapter的数据都是来源于服务器的,所以在获取服务器的时候就需要异步获取,这里就需要开线程了(线程池)去获取服务器的数据了.但这样有的时候adapter的中 ...
- Android学习四、Android中的Adapter
一.Adapter的介绍 An Adapter object acts as a bridge between an AdapterView and the underlying data for t ...
- Android 实现ListView中Item被单击后背景色保持高亮
今天为了解决一个需求,就是我有一个slidingDrawer,里面是一个ListView.然后,单击其中的Item,默认只是显示一个橙色背景后就恢复了.客户便有着个需求,需要单击这个Item的背景高亮 ...
随机推荐
- Jstorm与RocketMQ整合
如果是经常关注阿里巴巴的朋友们,看到我这篇博客的题目,就知道我在参加今年的中间件比赛. 好了,废话不说,开始了. 首先我们知道,rocketmq的consumer有两种,一种是DefaultMQPus ...
- Springmvc注解注入的简单demo
今天看了注解注入觉得确实简化了xml配置,一般情况下Spring容器要成功启动的三大要件分别是:Bean定义信息,Bean实现类,以及spring本身.如果采取基于XML的配置,Bean信息和Bean ...
- Spring Boot微服务架构入门
概述 还记得在10年毕业实习的时候,当时后台三大框架为主流的后台开发框架成软件行业的标杆,当时对于软件的认识也就是照猫画虎,对于为什么会有这么样的写法,以及这种框架的优势或劣势,是不清楚的,Sprin ...
- 发现----Android Demo
时间悄悄的走,转眼来实习已经三个月了,三个月的时间,小编慢慢的成长着,从刚开始的电商项目到现在的车段子项目,小编在走过一个又一个项目的同时,走过了一个又一个战胜自己的奇迹,每次遇到一个新的技术点,小编 ...
- tomcat配置集群
在Tomcat中使用集群功能相对简单.最简单的用法是直接在server.xml文件的或节点下添加 <Cluster className="org.apache.catalina.ha. ...
- 剑指Offer——回溯算法
剑指Offer--回溯算法 什么是回溯法 回溯法实际是穷举算法,按问题某种变化趋势穷举下去,如某状态的变化用完还没有得到最优解,则返回上一种状态继续穷举.回溯法有"通用的解题法"之 ...
- 安卓java.lang.IllegalStateException: The specified child already has a parent.解决方案
在使用ViewPager的时候遇到一个错误java.lang.IllegalStateException: The specified child already has a parent. You ...
- 【OpenGL】理解一些基本问题
写在前面 啦啦啦,搞了很久的Unity Shaders,越学越觉得基础知识很重要.学Unity Shader的时候,总会想,shader到底是什么呢?shader的pipeline是什么呢?它们是怎么 ...
- Cocos2D iOS之旅:如何写一个敲地鼠游戏(二):Cocos2D中的高清支持
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...
- AngularJS进阶(四十)创建模块、服务
AngularJS进阶(四十)创建模块.服务 学习要点 使用模块构架应用 创建和使用服务 为什么要使用和创建服务与模块? 服务允许你打包可重用的功能,使之能在此应用中使用. 模块允许你打包可重用的功能 ...