当前位置:操作系统 > 安卓/Android >>

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 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,