ListView和性能
一谈起ListView,我想大家都不陌生。而且最近该控件特别红,像QQ,人人和新浪客户端里都有它的影子。
其实实现ListView非常的简单。
我想大家都用过各种各样的控件,比如说一个最简单的TextView,我们都是在布局文件里加入TextView标签,然后在Activity里通过findViewById(int id)方法得到该对象的引用,最后调用TextView类的setText(CharSequence s)方法设置该控件的值。
同样,对于ListView,我们先在布局文件里这样添加标签:
[html]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/mylist"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
有了布局文件,然后我们在Activity里通过findViewById(int id)方法得到ListView对象的引用
[java]
ListView listView = (ListView) findViewById(R.id.mylist);
有了控件还不行,我们可以把ListView看作是一个可以伸缩的容器,我们需要往里添加内容。作为数据传输的桥梁,Adapter封装了所需的数据,通过调用ListView的方法setAdapter(Adapter a)将数据绑定到ListView中,这样屏幕上就有数据显示了。
Adapter是一个接口,定义了许多规范。Android提供了实现该接口的一些方便的类,如ArrayAdapter,CursorAdapter。下面以ArrayAdapter类为例讲解如何创建一个Adapter。
[java]
String[] values = new String[] { "Android", "iPhone", "WindowsMobile",
"Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X",
"Linux", "OS/2" };
// First paramenter - Context
// Second parameter - Layout for the row
// Third parameter - ID of the TextView to which the data is written
// Forth - the Array of data
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.易做图_list_item_1, android.R.id.text1, values);
是不是很简单?在上面的那个构造方法中,一共有四个参数,第一个参数很简单,就是一个上下文对象Context,第二个参数是描述每一行的布局,这里使用的是Android自带的一个简单布局,第三个参数是该View的id,最后一个是加入的数组。
上面的ArrayAdapter只能在每一行显示一些文本信息,如果想丰富一下,比如增加图片等,就需要继承该类,实现自己的自定义类。
[java
public class MySimpleArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private final String[] values;
public MySimpleArrayAdapter(Context context, String[] values) {
super(context, R.layout.rowlayout, values);
this.context = context;
this.values = values;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.rowlayout, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.label);
ImageView imageView = (ImageView) rowView.findViewById(R.id.icon);
textView.setText(values[position]);
String s = values[position];
imageView.setImageResource(R.drawable.ok);
return rowView;
}
}
继承该类最关键的就是复写getView()方法,因为ListView是通过该方法得到视图然后显示在屏幕上的。在本方法中,我们自定义了一个XML布局文件,里面有TextView标签和ImageView标签,分别用来显示文字和图片信息,这里是先得到系统服务LayoutInflater,调用该方法的inflate得到该布局的View,最后通过findViewById()方法获取TextView和ImageView的对象引用,再给它们赋值返回就结束了。
但是本章的讨论不是讲解如何实现ListView,但是考虑到有些没有接触过ListView的同志,就大概写了一点demo,同时以此例子为引子,指出该方法存在的一些性能问题。
由于通过调用LayoutInflater的inflate方法获得的View,其实会产生新的对象,创建对象是很耗时和资源的(内存),另外调用getViewById()方法也会相对耗时和耗资源,虽然其强度不如前者。
所以Android决定,如果代表每一行的View不可见(向下滑动,上面的View被遮住了,即为不可见),那么它将允许getView方法通过convertView复用该View,达到提升性能的目的。
我们先来看下ArrayAdapter是如何进行优化的。
[java]
public View getView(int position, View convertView, ViewGroup parent) {
return createViewFromResource(position, convertView, parent, mResource);
}
private View createViewFromResource(int position, View convertView, ViewGroup parent,
int resource) {
View view;
TextView text;
if (convertView == null) {
view = mInflater.inflate(resource, parent, false);
} else {
view = convertView;
}
try {
if (mFieldId == 0) {
// If no custom field is assigned, assume the whole resource is a TextView
text = (TextView) view;
} else {
// Otherwise, find the TextView field within the layout
text = (TextView) view.findViewById(mFieldId);
}
} catch (ClassCastException e) {
Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
throw new IllegalStateException(
"ArrayAdapter requires the resource ID to be a TextView", e);
}
T item = getItem(position);
if (item instanceof CharSequence) {
&n
补充:移动开发 , Android ,