Android ListView summary (multi-select box ListView, dynamic loading, multi-threaded update progress bar in ListView)

http://www.cnblogs.com/chon/archive/2011/06/28/2092317.html

 

Why ListView?

ListView If it is only for functional requirements, ListView may not exist. Basically, ScrollView can do what ListView can do. The most fundamental reason for the existence of ListView is its high efficiency ( how to achieve it? ). ListView reduces memory consumption through the reuse of objects, and also reduces the creation of objects and thus also reduces the consumption of cpu (creating View objects in Androidk Often accompanied by parsing xml). The essence of ListView is a bitmap (of course, all control texts, etc., will eventually become bitmaps when viewed on the screen). When scrolling, the position of the Item will be recalculated and a new bitmap will be drawn and displayed on the screen. This may not sound very efficient, but the advantage of this is that each time a View object is created for the first Item, objects of the same style can share a View object, reducing memory consumption. And the ListView is event-driven, it will only be redrawn when needed, and only the Items currently displayed on the screen will be drawn.

How To Use?

ListView is inseparable from Adapter. The usual practice is to create a class to inherit BaseAdapter, Override getCount() and getView() and other methods. Generate an object of this class, call setAdapter() of ListView to bind with ListViw.

How Does It work?

ListView will call the getCount() method of the Adapter bound to it to know how many items need to be displayed, and then call getView(int position, View convertView, ViewGroup parent) in a loop to know how to draw the first item, and draw it until the The current ListView's space fills up. When the data in the Adapter changes, you need to call notifyDataSetChanged () to tell the Adapter that the data has changed or register an observer for the Adapter registerDataSetObserver (DataSetObserver observer). When the Adapter learns that the data bound to it has changed, it will call the getCount() method again, and call getView(int position, View convertView, ViewGroup parent) in a loop to refresh the current page.

Item 1

Item 2

Item 3

Item 4

Item 5

Item 6

Item 7

Item 8

当这个ListView 向上滚动需要创建一个Item9 同时,有些对象(比如Item1 )不在显示区域将看不到,这时android 将会把item1 的 引用传递给 Adapter.getView() 中的convertView这样我们就不用再创建一个View来存放Item9,只需要把原来的item1对象作下修改,就可以重复使用了 ;我们也不用担心convertView 是不是正确的类型,这个由系统保证,所以我们要作的就是把convertView 转换(经常需要向下转型)成我们自己的View 再给它赋值,in this case :(TextView) convertView.setText(“Item9”);

 

复制代码
public View getView( int position, View convertView, ViewGroup parent) {
if (convertView == null ) {
// this would be first time to show the item,so we need to create it
convertView = mInflater.inflate(R.layout.item, null );
}
// we grab the convertView,modify it and reuse it
((TextView) convertView.findViewById(R.id.text)).setText(DATA[position]);
return convertView;
}
复制代码

调用方法所需要的消耗要比访问变量高得多,而上面的代码一次又一次的调用findViewById()方法,作着重复的事情。所以我们可以进一步进行如下优化: 创建一个类用来保存一些View的引用,这样我们就可以直接使用,而不用再调用findViewById().因为我们所保存的只是引用不是对象本身,所以不用担心会占用大量内存

复制代码
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();
}
// we store the reference ,so that we don’t have to call findViewById() over and over again
holder.text.setText(DATA[position]);
holder.icon.setImageBitmap((position
& 1 ) == 1 ? mIcon1 : mIcon2);
return convertView;
}
复制代码

上图是T-mobile g1上采集的的数据,现在看来可能现在不是很准确,但其性能上的差异还是很有参考价值的。

Tips & Tricks

ListView是为了大容量数据展示而设计的。如果数据量(Item的数量)不是很大,且用ListView实现起来比较麻烦,不妨换种思路,不使用ListView,而用ScrollView来实现。

如果Item信息布局比较复杂或者Item的数量很多,出于性能的考虑,建议自定义一个View组件实现需要的功能,而不是组合其它控件达到所要的效果。

ListView滚动变黑:在xml中给ListView增加一个属性android:cacheColorHint="#00000000" 。当ListVIew中有很多Item,有时候需要快速的滚动。比如从第一个Item滚动到第600个Item这个时候,中间的很多Item对用户来说意义不是很大,但android却要调用 adapter.getView()方法将这些Item逐一画出,并且因为滚动很快用户不希望有任何的延迟。这在一些低端手机比如g1,是很难作到的。所以google工程师想出的一个办法是在滚动的时候,让屏幕变黑用一张黑色bitmap盖住ListView,而不去绘制中间过程中的很多Item,从而提升性能。

Item有自己的背景盖住了Selector光标:在xml中给ListView增加一个属性:android:drawSelectorOnTop="true"这样光标就会跑到Item上面的图层,解决我们的问题。

Snippets

多选框ListView

   

带有进度条的ListView,多个子线程刷新各自的进度,如果子线程很多那么刷新就会变得很频繁,我们可以由一个handler负责统一刷新,这样我们就要以增加一些额外条件限制刷新的次数和条件

分批加载的原理很简单,给ListView添加一个OnScrollListener监听滚动事件,当用户滚动到屏幕到特定的位置时加载新数据,并给LIstView加一个正在加载的footerView,当加载数据结束时再把这个footerView去掉。

如果有什么疑问,发现bug或者有更好的想法或者建议,或者附件无法下载。请发邮件至[email protected]

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326735504&siteId=291194637