关于BaseAdapter的使用及优化心得(一)
对于Android程序员来说,BaseAdapter肯定不会陌生,灵活而优雅是BaseAdapter最大的特点。开发者可以通过构造BaseAdapter并搭载到ListView或者GridView这类多控件布局上面,实现软件所需要的布局效果。同时,BaseAdapter也是适配器里面最基础的一个类,其他的例如SimpleAdapter、ArrayAdapter都是直接或者间接继承BaseAdapter,所以说学好BaseAdapter基本就熟练掌握了适配器的使用了。
本文需要具备一些Android基础知识的前提下才能更好的理解,因为本文并不是介绍BaseAdapter的基本使用方法,如果对于BaseAdapter不了解可以去参考一下文档。在这里主要是介绍一下BaseAdapter的实现细节和怎么优化BaseAdapter的设计,从而节省我们宝贵的手机运行资源。对于老鸟高手来说,这可能是一个常识了,还是主要给那些像我以前一样刚刚入门的开发者的一点点参考,也希望高手来多多指正。
话不多说,我们看一看某些社交软件的界面(网上找的。。。。。)

这个列表项就是用ListView作为布局,搭载SimpleAdapter或者BaseAdapter作为数据源做成的界面效果。一般来说,很多软件的界面都运用这个方法来实现想要的布局效果。我在这里说明一下后面说到的名词,首先这是一个列表项,里面有各个数据项,例如图片+文件传输助手+test+时间就是一个数据项,它是一个View视图,这张图片里面一共就有8个数据项,由8个View视图按垂直方向排列而成。OK,我们开始步入正题。
假设,我们还是用例子讲解比较好理解,所以呢我们假设这个列表里面一共有40个数据项,而作为手机界面的限制,它一次只能显示8个数据项,同时它的另外32个数据项是隐藏状态。而显示这8个数据项就需要8个View实例,也就是需要实例化8个View的子类来显示内容,此时系统就有8个View实例占据内存空间。那如果我们把手指往下一滑动呢,自然顶端的数据项就会被隐藏,而底端的数据项自然就显示出来,那么这时候需要在new一个新的View实例来吗?如果还是继续创建实例,那么系统内存空间就有9个View实例了,可是我们还是只需要8个View实例就可以在手机屏幕完全显示,而顶端的被隐藏的实例话是可以不存在的了。所以这么来说,这样就浪费了手机的运行资源了。
为了解决这个问题,我们在BaseAdapter中可以对View进行重用,也就是将被隐藏的View改变为将要显示的View并返回出来。
在BaseAdapter中,这个抽象方法非常重要,它就是根据position的值返回对象的数据项的View视图,所以我们主要也是围绕这个方法来达到效率上优化的目的。
public View getView(int position, View convertView, ViewGroup parent) { return null; }
简单介绍一下这个函数的参数,position是ID索引值,也就是ListView的对应的数据项的序号,而convertView则是View视图复用的基础,如果为第一个页面的数据,它的值为null,所以我们可以根据convertView的值来决定我们是否要new一个View的实例出来。
参见下面代码
1 @Override
2 public View getView(int position, View convertView, ViewGroup parent) {
3 if(convertView == null){
4 convertView = new TextView(context);//新建一个字符串控件
5 ((TextView)convertView).setText(position);//实现其是第几个数据项
6 }
7 else{
8 ((TextView)convertView).setText(position);//重新修改其是第几个数据项
9 }
10 return convertView;
11 }
为了简单起来,我这里的View只是一个简简单单的字符串控件,在代码中我们可以看到,先对convertView进行判断,如果其值为null,则说明该方法此时返回的View是第一页的视图,所以需要new出一个View的实例,然后对其进行设置显示的内容并返回(这里设置的内容为position)。如果其值不为null,则说明此时的View视图是可以复用其他已经隐藏的View实例,而convertView的索引就是这个隐藏的实例,自然我们不用重新创建一个新的View实例而直接对convertView进行重新设置数值并返回便可。
这样就保证了程序里面只有足够界面显示的View实例的个数存在,而不会有多余的View来占用系统资源,由此也提高了一点点效率。
这是BaseAdapter的效率优化的一个方面,接下来我们还要说一下另外一个方面,说明白了也就是一个小技巧来提高效率。对于一个BaseAdapter来说,显示的界面肯定不是仅仅的一两个字符串控件(不然我们就用ArrayAdapter了多简便),而一般是加载一个根据layout生成的布局控件,相对来说这个的布局控件会比较复杂,我们会对其的子控件进行获取并赋值返回,所以我们经常要调用findViewById()这个方法来或者子控件的引用。而findViewById()会比较消耗系统资源,频繁的调用在我们快速滑动界面时会加重手机的负担,所以我们也可以对这个地方进行一些小小的改进。
参考这个代码
public class PersonAdapter extends BaseAdapter {
private List<Person> persons;//绑定的数据
private int resource;//绑定的Layout数据项界面
private LayoutInflater inflater;//布局填充服务
public PersonAdapter(Context context, List<Person> persons, int resource) {
this.persons = persons;
this.resource = resource;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return persons.size();
}
@Override
public Object getItem(int position) {
return persons.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView nameView = null;
TextView phoneView = null;
if(convertView == null){
convertView = inflater.inflate(resource, null);//生成绑定数据的View界面
nameView = (TextView) convertView.findViewById(R.id.name);
phoneView = (TextView) convertView.findViewById(R.id.phone);
ViewCache cache = new ViewCache();
cache.nameView = nameView;
cache.phoneView = phoneView;
convertView.setTag(cache);
}else{
ViewCache cache = (ViewCache) convertView.getTag();
nameView = cache.nameView;
phoneView = cache.phoneView;
}
Person person = persons.get(position);
//下面代码实现数据绑定
nameView.setText(person.getName());
phoneView.setText(person.getPhone());
return convertView;
}
/**
*保存findViewById获得的子控件索引的内部类
*/
private final class ViewCache{
public TextView nameView;
public TextView phoneView;
}
}
重点还是放在getView()这个方法上。在代码里面,我写了一个ViewCache的私有内部类,主要用来保存要来复用的View所需要获得的子控件的索引值。稍微解释一下代码,如果convertView为null,则说明需要new出一个View实例,在这里就是调用Inflater这个系统服务根据resource这个界面的ID值来生成一个View实例,然后用findViewById这个方法来或者其中的子控件的值,并保存在内部类ViewCache中,放入Tag中,setTag(object)是可以放入一个任意的类来保存成为缓存,因为其是Object。最后设置View子控件的内容并返回。如果不为null呢,现在则需要重用View实例了,所以我们也顺带重用一下保存在Tag里面的ViewCache的类成员变量的子控件索引值,而不需要重新去一个一个调用findViewById()这个方法,在界面足够复杂时这样是可以节省很多系统资源的。
这就是BaseAdapter提高效率的两种小技巧,如果大牛有其他更好的技巧,也希望能分享分享用来学习一下。
作者:enjoy风铃
出处:http://www.cnblogs.com/net168/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则下次不给你转载了。
关于BaseAdapter的使用及优化心得(一)的更多相关文章
- VMware 11安装Mac OS X 10.11.5虚拟机以及优化心得
随着苹果WWC大会退出了MAC最新版的10.11.5,本着一颗“极客”的心情,在第一时间用VMWARE虚拟机装上了.然后各种卡顿这里分享一下优化mac虚拟机的心得. 1 从Dock上移除Dashboa ...
- Android ListView使用BaseAdapter与ListView的优化 (转至 http://www.open-open.com/lib/view/open1339485728006.html)
在ListView的使用中,有时候还需要在里面加入按钮等控件,实现单独的操作.也就是说,这个ListView不再只是展示数据,也不仅仅是这一行要来处理用户的操作,而是里面的控件要获得用户的焦点.读者可 ...
- MySQL优化心得
一打开科技类论坛,最常看到的文章主题就是MySQL性能优化了,为什么要优化呢? 因为: 数据库出现瓶颈,系统的吞吐量出现访问速度慢 随着应用程序的运行,数据库的中的数据会越来越多,处理时间变长 数据读 ...
- MongoDB优化心得分享
这里总结下这段时间使用mongo的心得,列出了几个需要注意的地方. 1. 系统参数及mongo参数设置 mongo参数主要是storageEngine和directoryperdb,这两个参数一开始不 ...
- Oracle IO优化心得
很多的时侯,做Oracle DBA的我们,当应用管理员向我们通告现在应用很慢.数据库很慢的时侯,我们到数据库时做几个示例的Select也发现同样的问题时,有些时侯我们会无从下手,因为我们认为数据库的各 ...
- BaseAdapter中重写getview的心得以及发现convertView回收的机制
以前一直在用BaseAdapter,对于其中的getview方法的重写一直不太清楚.今天终于得以有空来探究它的详细机制. 下面先讲讲我遇到的几个问题: 一.View getview(int posit ...
- js查重去重性能优化心得
概述 今天产品反映有个5000条数据的页面的保存按钮很慢,查看代码看到是因为点击保存按钮之后,进行了查重操作,而查重操作是用2个for循环完成了,时间复杂度是O(n^2).没办法,只能想办法优化一下了 ...
- Linux的php-fpm优化心得-php-fpm进程占用内存大和不释放内存问题(转)
原文地址:https://wzfou.com/php-fpm/ 最近发现博客的内存老是隔三差五地被“吃掉”了,登录到后台后偶尔会出卡顿的情况,一开始怀疑是Swap不够导致的,于是给VPS主机增加了几个 ...
- .NET/C# 优化心得
网上的优化千篇一律,遂干脆自己写一个,总结总结网上说的与自己的想法. 1.关于sql方面的优化,详见Mysql语句的优化 2.对于不常更新的网页,使用静态页,使用 cdn 加速. 3.关于主从同步,如 ...
随机推荐
- EntityFramework追踪Sql语句
方法一:SQL Profile 这个工具只有sql标准版(standard) 及以上版本才有,我装的是SqlServer2012 Express,所以采用方法2. 方法二:EntityFramewor ...
- 在vs2005中使用AnkhSvn服务端IP改变无法连接
1.打开VS2005,选择文件-->Subversion-->Pending Changes 2.在弹出的对话框中 选择other. 荆州古城
- Android开发教程app下载无法成功创建问题
本文明来给各位同学介绍一下关于cordova cteate app 时下载失败无法成功创建的解决方法,有碰到此问题的同学可进入参考. 使用如下语句创建一个cordova应用: 代码如下 cordova ...
- CentOS学习笔记--基本命令--文件与目录管理
Linux基本命令--文件与目录管理 本节节选自鸟哥的 Linux 私房菜 -- 基础学习篇目录 第七章.Linux 文件与目录管理 ls(文件与目录的检视) ls命令就是list的缩写,ls可以 ...
- Linux rename命令
转载:http://blog.csdn.net/sea_shore/article/details/6102437 1.rename命令批量修改文件名, 其实linux下可以使用别的办法来批量修改文件 ...
- DPDK多核多线程机制简析
DPDK通过在多核设备上,创建多个线程,每个线程绑定到单独的核上,减少线程调度的开销,以提高性能. DPDK的线程分为控制线程和数据线程,控制线程一般绑定到MASTER核上,主要是接受用户配置,并传递 ...
- POJ C++程序设计 编程题#4:魔兽世界之一:备战
编程题#4:魔兽世界之一:备战 来源: POJ(Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 ...
- winfrom之动态控件生成以及保存动态空间的数据
前些天要完成一个winform程序,里面涉及到动态控件的添加以及保存动态空间中数据的保存,效果如下 初始化时: 点击添加阶梯价后:(点击一下,动态添加一行) 那么接下来,我们就具体的讲下代码实现: 首 ...
- ASP.NET中实现页面间的参数传递
ASP.NET中实现页面间的参数传递 编写人:CC阿爸 2013-10-27 l 近来在做泛微OA与公司自行开发的系统集成登录的问题.在研究泛微页面间传递参为参数,综合得了解了一下现行页面间传参 ...
- MySQL的相关概念介绍
MySQL 为关系型数据库(Relational Database Management System), 这种所谓的"关系型"可以理解为"表格"的概念, 一个 ...