ListView 编程: 如何优化自定义 Adapter

来源:互联网 发布:mac 文件夹灰色打不开 编辑:程序博客网 时间:2024/06/02 11:37

出处:http://blog.csdn.net/androidbluetooth/article/details/6960936


使用自定义的 Adapter,需要优化,说到底是优化我们自定义的适配器类!

再说到底就是优化回调方法 getView 方法。



利用 convertView 这个参数,而不去在 getView 方法中重新创建一个临时的变量 View 了,

那么可以减轻虚拟机(回收)的负担,从而提高效率。


方案 1_ 优化代码: 使用 convertView 


@Override
public View getView(int position, View convertView, ViewGroup parent) {
    Log.d("mark", "getView() is invoked!" + "position = " + position + ","
        + "convertView = " + convertView + "," + "parent = " + parent);
    if (convertView == null) {
       convertView = inflater.inflate(R.layout.custom_fileview, null);
    }


    ((ImageView) convertView.findViewById(R.id.image_pic))
        .setImageResource(R.drawable.file);
    ((TextView) convertView.findViewById(R.id.text_content))
        .setText("fileName");

    return convertView;
}


可以看出,只有 convertView == null 为真(上面测试已经说明 convertView 何时为 null),

才去创建 View 对象。

如果你有兴趣的话,可以再次运行 APP 可以看出从底部再次滚动到顶部,

反复几次,你会发现几乎很少创建 View 对象,而是重复利用原来已经存在的 View 对象。

下面还有一种方式来优化代码,不说是最好但至少是 even better  (Google 推荐)!


方案 2_ 优化代码:hold 一把


在 android 提供的 APIDemo 中(List14.java)使用了 ViewHolder ,

所以 ViewHolder 不是 android 自带的 api,也不是什么诡异的东西。


@Override
public View getView(int position, View convertView, ViewGroup parent) {
    Log.d("mark", "getView() is invoked!" + "position = " + position + ","
        + "convertView = " + convertView + "," + "parent = " + parent);

    ViewHolder vHolder = null;

    if (convertView == null) {
         convertView = inflater.inflate(R.layout.custom_fileview, null);
         // 創建 ViewHodler 對象
         vHolder = new ViewHolder();
         vHolder.pic = (ImageView) convertView.findViewById(R.id.image_pic);
         vHolder.content = (TextView) convertView
             .findViewById(R.id.text_content);
         // 設置 Tag
        convertView.setTag(vHolder);
        } else {
            vHolder = (ViewHolder) convertView.getTag();
       }
      vHolder.pic.setImageResource(R.drawable.file);
      vHolder.content.setText("fileName");
      return convertView;
}


其中 ViewHolder 是 FileViewAdapter 的 一个静态内部类。

static class ViewHolder {
    TextView content;
    ImageView pic;
}


使用 ViewHolder 的关键好处是缓存了显示数据的视图,加快了 UI 的响应速度。


到目前为止,仿佛优化工作已经 ok,其实,

还有一个小问题: ImageView 使用的图片资源需要预处理。


FileViewAdapter 完整的代码如下:

[java] view plaincopyprint?
  1. package mark.zhang;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.content.Context;  
  6. import android.graphics.Bitmap;  
  7. import android.graphics.BitmapFactory;  
  8. import android.util.Log;  
  9. import android.view.LayoutInflater;  
  10. import android.view.View;  
  11. import android.view.ViewGroup;  
  12. import android.widget.BaseAdapter;  
  13. import android.widget.ImageView;  
  14. import android.widget.TextView;  
  15.   
  16. public class FileViewAdapter extends BaseAdapter {  
  17.     private LayoutInflater inflater = null;  
  18.     private ArrayList<String> arrays = null;  
  19.     private Bitmap showIcon = null;  
  20.   
  21.     public FileViewAdapter(Context context, ArrayList<String> arrays) {  
  22.         this.arrays = arrays;  
  23.         inflater = LayoutInflater.from(context);  
  24.         // 處理圖片資源  
  25.         showIcon = BitmapFactory.decodeResource(context.getResources(),  
  26.                 R.drawable.file);  
  27.     }  
  28.   
  29.     @Override  
  30.     public int getCount() {  
  31.         // Log.d("mark", "getCount() is invoked!");  
  32.         // 返回需要顯示的 item 數目  
  33.         // 這次是外界提供的數據,與上次代碼有差異  
  34.         return arrays.size();  
  35.     }  
  36.   
  37.     @Override  
  38.     public Object getItem(int position) {  
  39.         // Log.d("mark", "getItem() is invoked!");  
  40.         return position;  
  41.     }  
  42.   
  43.     @Override  
  44.     public long getItemId(int position) {  
  45.         // Log.d("mark", "getItemId() is invoked!");  
  46.         // Log.d("mark", "position = " + position);  
  47.         return position;  
  48.     }  
  49.   
  50.     @Override  
  51.     public View getView(int position, View convertView, ViewGroup parent) {  
  52.         Log.d("mark""getView() is invoked!" + "position = " + position + ","  
  53.                 + "convertView = " + convertView + "," + "parent = " + parent);  
  54.   
  55.         ViewHolder vHolder = null;  
  56.   
  57.         if (convertView == null) {  
  58.             convertView = inflater.inflate(R.layout.custom_fileview, null);  
  59.             // 創建 ViewHodler 對象  
  60.             vHolder = new ViewHolder();  
  61.             vHolder.pic = (ImageView) convertView.findViewById(R.id.image_pic);  
  62.             vHolder.content = (TextView) convertView  
  63.                     .findViewById(R.id.text_content);  
  64.             // 設置 Tag  
  65.             convertView.setTag(vHolder);  
  66.         } else {  
  67.             vHolder = (ViewHolder) convertView.getTag();  
  68.         }  
  69.         // 設置位圖  
  70.         vHolder.pic.setImageBitmap(showIcon);  
  71.         vHolder.content.setText("fileName");  
  72.         return convertView;  
  73.     }  
  74.   
  75.     static class ViewHolder {  
  76.         TextView content;  
  77.         ImageView pic;  
  78.     }  
  79. }  

最后强调一下,要在布局文件里面将 ListView 控件的属性设置为:


    android:layout_width="fill_parent"
    android:layout_height="fill_parent"


关于 ListView 的工作原理(Recycler)以及如何进一步优化 ListView,可以参考

http://mzh3344258.blog.51cto.com/1823534/889879


Google IO 文档下载

http://download.csdn.net/detail/androidbluetooth/3783925

原创粉丝点击