ListView的Adapter的作用如下图所示:
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(R.drawable.icon);
- }
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(R.drawable.icon);
}
怎么样?如果超过1000000项时,后果不堪设想!您可千万别这么写!
优化方案:
方案一:
- public View getView(int position, View convertView, ViewGroup parent) {
-
- if (convertView == null) {
- convertView = mInflater.inflate(R.layout.item,
null);
- }
-
- ((TextView) item.findViewById(R.id.text)).setText(DATA[position]);
- ((ImageView) item.findViewById(R.id.icon)).setImageBitmap(R.drawable.icon);
- }
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item, null);
}
((TextView) item.findViewById(R.id.text)).setText(DATA[position]);
((ImageView) item.findViewById(R.id.icon)).setImageBitmap(R.drawable.icon);
}
上面的系统将会减少创建很多View。性能得到了很大的提升。
方案2:
- 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(R.drawable.icon);
- return convertView;
- }
-
- 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);//给View添加一个格外的数据
} else {
holder = (ViewHolder) convertView.getTag();//将上面的holder数据取出来
}
holder.text.setText(DATA[position]);
holder.icon.setImageBitmap(R.drawable.icon);
return convertView;
}
static class ViewHolder {
TextView text;
ImageView icon;
}
怎么样?会不会又给您的系统带来很大的提升呢?看看下面三种方式的性能对比图您就知道了!
可以发现,只有第一屏(可视范围)调用getView所消耗的时间远远多于后面的,通过对
convertView == null内代码监控也是同样的结果。
也就是说ListView仅仅缓存了可视范围内的View,随后的滚动都是对这些View进行数据更新。不管你有多少数据,他都只用ArrayList缓存可视范围内的View,这样保证了性能,也造成了我以为ListView只缓存View结构不缓存数据的假相(不会只有我一人这么认为吧- - #)。这也能解释为什么GOOGLE优化方案一比二高很多的原因。那么剩下的也就只有findViewById比较耗时了。据此大家可以看看AbsListView的源代码,看看
obtainView这个方法内的代码及RecycleBin这个类的实现,欢迎分享。
- if (convertView ==
null) {
- convertView = mInflater.inflate(R.layout.list_item_icon_text,
null);
- ((ImageView) convertView.findViewById(R.id.icon1)).setImageResource(R.drawable.icon);
- ((TextView) convertView.findViewById(R.id.text1)).setText(mData[position]);
- ((ImageView) convertView.findViewById(R.id.icon2)).setImageResource(R.drawable.icon);
- ((TextView) convertView.findViewById(R.id.text2)).setText(mData[position]);
- }
- else
- return convertView;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
((ImageView) convertView.findViewById(R.id.icon1)).setImageResource(R.drawable.icon);
((TextView) convertView.findViewById(R.id.text1)).setText(mData[position]);
((ImageView) convertView.findViewById(R.id.icon2)).setImageResource(R.drawable.icon);
((TextView) convertView.findViewById(R.id.text2)).setText(mData[position]);
}
else
return convertView;
没错,你会发现滚动时会重复显示第一屏的数据!
子控件里的事件因为是同一个控件,也可以直接放到convertView == null 代码块内部,如果需要交互数据比如position,可以通过tag方式来设置并获取当前数据。
这里推荐如果只是一般的应用(一般指子控件不多),无需都是用静态内部类来优化,使用方案1即可;反之,对性能要求较高时可采用。此外需要提醒的是这里也是用空间换时间的做法,View本身因为setTag而会占用更多的内存,还会增加代码量;而findViewById会临时消耗更多的内存,所以不可盲目使用,依实际情况而定。
分享到:
相关推荐
Android高手进阶教程之----Android中万能的BaseAdapter(Spinner,ListView,GridView)的使用!.doc Android高手进阶教程之----通过Location获取Address的使用.doc Android基础教程之----Android ProgressBar的使用.doc...
android-world-of-listview-android
MVC-ListView-DataModel-master.zipMVC-ListView-DataModel-master.zipMVC-ListView-DataModel-master.zipMVC-ListView-DataModel-master.zipMVC-ListView-DataModel-master.zipMVC-ListView-DataModel-master....
Android-ListView-Example
Android开发笔记---ListView
Android--开发--ListView上下翻页效果
Android--开发-- ListView下拉刷新 Demo
For more details, visitAnimated-Expanding-ListView Developed by @LeonardoCardoso. Animated Expanding ListView provides a fancy animation on expanding or collapsing the content of a listview item. It...
源码参考,欢迎下载
Android--开发--ListView 中的item随意拖动
SimpleAdater 简单适配器 配合listView使用 ,将数据展示在列表中 进阶1
Android--开发--ListView 实现点击侧边A-Z快速查找
android listview事件详解。
仿miui7文件管理(文件管理-->最近),头部有固定分类的ListView
21.[开源][安卓][拖拽]drag-sort-listview-master DragSortListView(DSLV)是Android ListView的一个扩展,支持拖拽排序和左右滑动删除功能。重写了TouchInterceptor(TI)类来提供更加优美的拖拽动画效果。 DSLV...
•Android---UI篇---Tab Layout(选项卡布局) • •Andorid---UI篇---TableLayout(表格布局) ...•Android---UI篇---ListView之SimpleCursorAdapter(列表)---3 • •Android---UI篇---Menu(菜单)
Android-react-native-timeline-listview.zip,React本机应用程序的时间线组件,安卓系统是谷歌在2008年设计和制造的。操作系统主要写在爪哇,C和C 的核心组件。它是在linux内核之上构建的,具有安全性优势。
Android--开发--ListView保持在列表的顶部固定View 案例分析 源码
Android应用源码之drag-sort-listview-master.zip项目安卓应用源码下载Android应用源码之drag-sort-listview-master.zip项目安卓应用源码下载 1.适合学生毕业设计研究参考 2.适合个人学习研究参考 3.适合公司开发...
Android高级应用源码-listview 适配器 优化 重用.zip