ListView适配器Adapter介绍与优化
一、ListView与Adapter的关系

ListView是Android开发过程中较为常见的组件之一,它将数据以列表的形式展现出来。一般而言,一个ListView由以下三个元素组成:
1、View,用于展示列表,通常是一个xml所指定的。大家都知道Android的界面基本上是由xml文件负责完成的,所以ListView的界面也理所应当的使用了xml定义。例如在ListView中经常用到的“android.R.layout.simple_list_item”等, 就是Android系统内部定义好的一个xml文件。
2、适配器,用来将不同的数据映射到View上。不同的数据对应不同的适配器,如BaseAdapter、ArrayAdapter、CursorAdapter、SimpleAdapter等, 他们能够将数组、指针指向的数据、Map等数据映射到View上。也正是由于适配器的存在,使得ListView的使用相当灵活,经过适配器的处理后,在 view看来所有的数据映射过来都是一样的。
3、数据,具体的来映射数据和资源,可以是字符串,图片等。通过适配器,这些数据将会被实现到 ListView上。所有的数据和资源要显示到ListView上都通过适配器来完成。
系统已有的适配器可以将基本的数据显示到ListView上,如:数组,Cursor指向的数据,Map里的数据。但是在实际开发中这些系统已实现的适配器,有时不能满足我们的需求。而且系统自带的含有多选功能ListView在实际使用过程中会有一些问题。要实现复杂的ListView可以通过继承ListView并重写相应的方法完成,同时也可以通过继承BaseAdapter来实现。
二、ListView绘制流程

public abstract class BaseAdapter——抽象类,继承它需要实现较多的方法,所以就具有较高的灵活性,实现了ListAdapter和SpinnerAdapter。
BaseAdapter需要重写的方法:
getCount(),
getItem(int position),
getItemId(int position),
getView(int position, View convertView, ViewGroup parent)
ListView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到 listView的长度,然后根据这个长度,调用getView()逐一绘制每一行。如果你的 getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。
系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的布局。我们用LayoutInflater的方法将定义好的item.xml文件提取成View实例用来显示。然后将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个 ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那再绘制下一行,直到绘完为止。
三、ListView优化
Adapter的作用就是ListView界面与数据之间的桥梁,当列表里的每一项显示到页面时,都会调用Adapter的getView方法返回一个View。在我们的列表有1000000项时会占用极大的系统资源。先看看下面的代码:

public View getView(int position, View convertView, ViewGroup parent)
{
View item = mInflater.inflate(R.layout.list_item_icon_text, null);
((TextView) item.findViewById(R.id.text)).setText(DATA[position]);
((ImageView) item.findViewById(R.id.icon)).setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
return item;
}

如果超过1000000项时,后果不堪设想!您可千万别这么写!我们再来看看下面的代码:

public View getView(int position, View convertView, ViewGroup parent)
{
if (convertView == null)
{
convertView = mInflater.inflate(R.layout.item, null);
}
((TextView) convertView.findViewById(R.id.text)).setText(DATA[position]);
((ImageView) convertView.findViewById(R.id.icon)).setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
return convertView;
}

怎么样,上面的代码是不是好了很多?系统将会减少创建很多View。性能得到了很大的提升。还有没有优化的方法呢? 答案是肯定的,采用ViewHolder模式:

class ChatListAdapter extends BaseAdapter
{
static class ViewHolder
{
TextView text;
ImageView icon;
} public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if (convertView == null)
{
convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(DATA[position]);
holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
return convertView;
}
}

怎么样?会不会又给您的系统带来很大的提升呢?看看下面三种方式的性能对比图您就知道了!

四、总结:用ViewHolder模式优化ListView
ViewHolder的作用:优化显示效率,即之前显示过的不用再从布局文件读取,直接从缓存中读取。可以看到它只是一个静态类,它的作用就在于减少不必要的调用findViewById。完整的官方例子中convertView 也是避免inflating View。然后把对底下的控件引用存在ViewHolder里面,再用convertView.setTag(holder)把它放在view里,下次就可以用(ViewHolder) convertView.getTag()直接取了。
ListView适配器Adapter介绍与优化的更多相关文章
- 自定义ListView适配器Adapter引用布局文件的情况下实现点击列表项时背景颜色为灰色
listview控件设置适配器的时候,如果使用自定义的adapter,比如MyArrayAdapter extends ArrayAdapter<String> 如果listitem布局文 ...
- ListView和Adapter数据适配器的简单介绍
ListView 显示大量相同格式数据 常用属性: listSelector listView每项在选中.按下等不同状态时的Drawable divider ...
- android之ListView,详细介绍实现步骤,举例,自定义listview适配器
android之ListView,详细介绍实现步骤,举例,自定义listview适配器 本文来源于www.ifyao.com禁止转载!www.ifyao.com android中如何使用listVie ...
- 代码优化>>>Android ListView适配器三级优化详解
转载本专栏每一篇博客请注明转载出处地址,尊重原创.此博客转载链接地址:点击打开链接 http://blog.csdn.net/qq_32059827/article/details/52718489 ...
- [Rosa]Android ListView 适配器原理及优化(转)
ListView的Adapter的作用如下图所示: Adapter的作用就是ListView界面与数据之间的桥梁,当列表里的每一项显示到页面时,都会调用Adapter的getView方法返回一个V ...
- Android listview与adapter用法
listview与adapter用法 博客分类: android 一个ListView通常有两个职责. (1)将数据填充到布局. (2)处理用户的选择点击等操作. 第一点很好理解,ListView ...
- ListView 和 Adapter用法
一个ListView通常有两个职责. (1)将数据填充到布局. (2)处理用户的选择点击等操作. 第一点很好理解,ListView就是实现这个功能的.第二点也不难做到,在后面的学习中读者会发现,这非常 ...
- 安卓开发笔记——打造万能适配器(Adapter)
为什么要打造万能适配器? 在安卓开发中,用到ListView和GridView的地方实在是太多了,系统默认给我们提供的适配器(ArrayAdapter,SimpleAdapter)经常不能满足我们的需 ...
- 【转】Android listview与adapter用法
一个ListView通常有两个职责. (1)将数据填充到布局. (2)处理用户的选择点击等操作. 第一点很好理解,ListView就是实现这个功能的.第二点也不难做到,在后面的学习中读者会发现,这非常 ...
随机推荐
- 洛谷P1044 栈(Catalan数)
P1044 栈 题目背景 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈). 栈的重要 ...
- 程序员除了会CRUD之外,还应该知道什么叫CQRS!
今天主要跟大家分享一下什么是 CQRS,以及在项目中如何去使用. CRUD系统 我们平常最熟悉的就是三层架构,通常都是通过数据访问层来修改或者查询数据,一般修改和查询使用的是相同的实体.然后通过业 ...
- 原生JS和jQuery中基本的节点操作
js中节点操作**document.createElement()**用来生成网页元素节点,参数为元素的标签名: **document.createTextNode()**用来生成文本节点,参数为所要 ...
- SQL Server插入中文乱码
如果数据库的Collocation是英文的,字段是varchar类型,向表中插入中文数据,会出现乱码. 解决方法: 方法1. 修改varchar 为 nvarchar类型, 并在插入数据前加N,例如: ...
- CentOS yum源的配置
yum操作 1.用YUM安装软件包命令:yum install 2.用YUM删除软件包命令:yum remove 3.使用YUM查找软件包命令:yum search4.列出所有可安装的软件包命令:yu ...
- java Integer
Java 中的数据类型分为基本数据类型和引用数据类型 int是基本数据类型,Integer是引用数据类型: Ingeter是int的包装类,int的初值为0,Ingeter的初值为null. 初始化 ...
- Zeppelin的入门使用系列之使用Zeppelin来运行Spark SQL(四)
不多说,直接上干货! 前期博客 Zeppelin的入门使用系列之使用Zeppelin来创建临时表UserTable(三) 1. 运行年龄统计的Spark SQL (1) 输入Spark SQL时,必 ...
- PHP+Mysql+jQuery找回密码
通常所说的密码找回功能不是真的能把忘记的密码找回,因为我们的密码是加密保存的,一般开发者会在验证用户信息后通过程序生成一个新密码或者生成一个特定的链接并发送邮件到用户邮箱,用户从邮箱链接到网站的重置密 ...
- C#关键字:yield
yield是C#为了简化遍历操作实现的语法糖.在语句中使用 yield 关键字,表示在该关键字所在的方法.运算符或 get 访问器是迭代器.有两种形式: yield return <expres ...
- 关于锚点页内链接跳转出现问题(不响应,没有反应)的解决方法(ZT)
我们知道,利用锚点可以实现页面链接跳转,也可以实现同一页面内的跳转功能. 例如:<a href="somepage.htm>某页面链接</a> 可以跳转链接到som ...