Android ListView列表控件的介绍和性能优化
listview列表控件
一、listview显示数据的原理:mvc模式
m:mode 数据(用javabean规范封装)
v:view listview
c:adapter 适配器,负责把数据展示到listview上
二、listview最常用适配器
baseadapter、simpleadapter、arrayadapter
三、listview显示数据的步骤
1.创建listview
2.自定义listview的适配器继承baseadapter,重写baseadapter的getcount方法和getview方法
3.创建自定义listview的适配器
4.listview设置适配器:listview.setadapter(adapter);
private class listviewadapter extends baseadapter{ //返回需要展示的数据的条数 @override public int getcount() { return 200; } //返回指定position位置对应的数据对象,一般很少用 @override public object getitem(int position) { return null; } //返回position位置对应id @override public long getitemid(int position) { return 0; } /** * 获取一个view,会作为listview的第position个item条目出现,用来显示listview的数据 * * @param convertview 历史缓存对象 */ @override public view getview(int position, view convertview, viewgroup parent) { view view ; if (convertview == null) { //创建新的view对象 view = view.inflate(mainactivity.this, r.layout.listview_item,null); }else{ //复用历史缓存view对象 view = convertview; } textview tv=(textview)view.findviewbyid(r.id.tv); tv.settext("item:" + position); return view; } }
四、listview的性能优化
1.listview的奇怪现象
问题:
如果listview的高度设为包裹内容,getview方法会多次调用
原因:
如果height设为”wrap_content”,为了把所有条目都显示出来,会多次校验数据是否可在屏幕显示完,(校验1次不保准,再多次校验)将多次调用getview方法
解决:以后再使用listview的时候,高度设置为填充父窗体 android:layout_height=”match_parent”
2.避免内存溢出优化:listview复用历史缓存view对象
问题:如果不复用历史缓存view对象,当listview的条目数过多,向下滑的很深时,会报错。
报错信息: e/dalvikvm-heap(2636): out of memory on a -294967280-byte allocation. 内存溢出
原因:不停创建新的view,消耗内存。为每一个item都创建一个view对象,必将占用很多内存空间。从xml中生成view,这是属于io操作,是耗时操作,所以必将影响性能
解决:可以对消失在屏幕的view进行缓存,当往下拖动时复用历史缓存,这样就只创建屏幕能显示的view个数的数量的view。getview方法有个参数convertview就是可以复用的历史缓存view对象。这个对象也可能为空,当它为空的时候,表示该条目view第一次创建,所以我们需要inflate一个view出来。
原理:android提供了一个叫做recycler(反复循环)的构件,就是当listview的item从滚出屏幕视角之外,对应item的view会被缓存到recycler中,相应的会从生成一个item,而此时调用的getview中的convertview参数就是滚出屏幕的缓存item的view,所以说如果能重用这个convertview,就会大大改善性能。
public view getview(int position, view convertview, viewgroup parent) { textview tv; if (convertview == null) { // 创建新的view 对象 tv = new textview(mainactivity.this); system.out.println(“创建新的view对象—” + position); } else { system.out.println(“复用历史缓存对象—” + position); view = (textview) convertview; } tv.settext(“4月14日科比告别战倒计时:” + position); return tv; }
3.item子控件显示卡顿优化:viewholder重用机制
问题:item中的子控件很多时加载慢。findviewbyid是到xml文件中去查找对应的id,可以想象如果组件多的话也是挺费事的,如果我们可以让view内的组件也随着view的复用而复用,那该是多美好的一件事。
原因:在getview()方法中的操作是先从xml中创建view对象(inflate操作,我们采用了重用convertview方法优化),然后在这个view去findviewbyid,找到每一个item的子view的控件对象,如:imageview、textview等。这里的findviewbyid操作是一个树查找过程,也是一个耗时的操作。
解决:谷歌推荐了一种优化方法来做应对,那就是重新建一个内部静态类,里面的成员变量跟view中所包含的组件个数类型相同
private static class viewholder {}
基本思路就是在convertview为null的时候,我们不仅重新inflate出来一个view,并且还需要进行findviewbyid的查找工作,但是同时我们还需要获取一个viewholder类的对象,并将findviewbyid的结果赋值给viewholder中对应的成员变量。最后将holder对象与该view对象“绑”在一块。当convertview不为null时,我们让view=converview,同时取出这个view对应的holder对象,就获得了这个view对象中的子控件,就是holder中的成员变量,这样在复用的时候,我们就不需要再去findviewbyid了,只需要在最开始的时候进行数次查找工作就可以了。这里的关键在于如何将view与holder对象进行绑定,那么就需要用到两个方法:view中的settag和gettag方法了。
经过上面的做法,可能大家感觉不太到优化的效果,根据google的文档,实际优化效果在百分之5左右。
4.网络数据过多加载缓慢优化
问题:
listview如果显示本地的list集合中的内容,list的长度也只有100个,我们可以毫不费力一次性加载完这100个数据;但是实际应用中,我们往往会需要使用listview来显示网络上的内容,比如说我们拿使用listview显示新闻为例:假如网络情况很好,我们使用的手机也许能够一下子加载完所有新闻数据,然后显示在listview中,用户可能感觉还好,假如说在网络不太顺畅的情况下,用户加载完所有网络的数据,可能这个list是1000条新闻,那么用户可能需要面对一个空白的activity好几分钟,这个显然是不合适的。
解决:
我们需要进行分批加载,比如说1000条新闻的list集合,我们一次加载20条,等到用户翻页到底部的时候,我们再添加下面的20条到list中,再使用adapter刷新listview,这样用户一次只需要等待20条数据的传输时间,不需要一次等待好几分钟把数据都加载完再在listview上显示。其次这样也可以缓解很多条新闻一次加载进行产生oom应用崩溃的情况。
5.加载数据过多内存溢出优化
问题:
我们知道android虚拟机给每个应用分配的运行时内存是一定的,一般性能不太好的机器只有16m,好一点的可能也就是64m的样子,假如说我们现在要浏览的新闻总数为一万条,即便是网络很好的情况下,我们可以很快的加载完毕,但是多数情况下也会出现内存溢出从而导致应用崩溃的情况。
解决:
实际上,分批加载也不能完全解决问题,因为虽然我们在分批中一次只增加20条数据到list集合中,然后再刷新到listview中去,假如有10万条数据,如果我们顺利读到最后这个list集合中还是会累积海量条数的数据,还是可能会造成oom的情况,这时候我们就需要用到分页,比如说我们将这10万条数据分为1000页,每一页100条数据,每一页加载时都覆盖掉上一页中list集合中的内容,然后每一页内再使用分批加载,这样用户的体验就会相对好一些。
上一篇: Oracle SID存在解決方法
下一篇: Oracle 随机数
推荐阅读
-
Android ListView列表控件的介绍和性能优化
-
android开发实现列表控件滚动位置精确保存和恢复的方法(推荐)
-
Android通过LIstView显示文件列表的两种方法介绍
-
android下拉刷新ListView的介绍和实现代码
-
android ListView和ProgressBar(进度条控件)的使用方法
-
Android ListView列表控件的介绍和性能优化
-
android开发实现列表控件滚动位置精确保存和恢复的方法(推荐)
-
Android通过LIstView显示文件列表的两种方法介绍
-
记一次vue长列表的内存性能分析和优化
-
Android实现ListView控件的多选和全选功能实例