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就是实现这个功能的.第二点也不难做到,在后面的学习中读者会发现,这非常 ...
随机推荐
- Linux 之问题集锦(一)
1. 打开目录时,怎么只显示一个窗口 计算机 -- 编辑 -- 首选项 -- 行为 -- 总是总浏览器窗口中打开 2. linux中添加PATH时出现 Found a swap file by the ...
- Cinder服务使用
Cinder环境 Cinder配置 重新创建卷组cinder-volumes [root@openstack centos]# vgremove cinder-volumes Configuratio ...
- Keras实现MNIST分类
仅仅为了学习Keras的使用,使用一个四层的全连接网络对MNIST数据集进行分类,网络模型各层结点数为:784: 256: 128 : 10: 使用整体数据集的75%作为训练集,25%作为测试 ...
- uoj#400. 【CTSC2018】暴力写挂(边分治)
传送门 做一道题学一堆东西.jpg 猫老师的题--暴力拿的分好像比打挂的正解多很多啊--我纯暴力+部分分已经能有80了--正解没调对之前一直只有10分→_→ 先说一下什么是边分治.这个其实类似于点分治 ...
- MySQL下载与安装配置
一.Windows 上安装 MySQL Windows 上安装 MySQL 相对简单,最新版本下载地址: 官网:https://dev.mysql.com/downloads/mysql/ 下载步骤: ...
- mui框架使用心得
这段时间一直在用mui框架做项目,现在很多快速开发的app大部分是用MUI和APICloud开发的.所以我就把他们对比了一下. mui有自己的UI组件,我在项目中,很少用框架的UI组件,而使用框架的j ...
- 3.过滤数据 ---SQL
一.使用WHERE子句 SELECT prod_name, prod_price FROM Products WHERE prod_price = 3.49; 输出▼ prod_name prod_p ...
- [Java]三大特性之封装
封装这个我们可以从字面上来理解,简单来说就是包装的意思,专业点就是信息隐藏. 是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可 ...
- Codeforces Round #527-D1. Great Vova Wall (Version 1)(思维+栈)
time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...
- jQuery基础(1)
一.jQuery的介绍 1.为什么要使用jQuery? 在用js写代码时,会遇到一些问题,如下: 1)window.onload 事件有事件覆盖的问题,因此只能写一个事件: 2)代码容错性差: 3)浏 ...