listview处理不同类型数据缓存

本文介绍了一种在Android ListView中实现数据分组并优化滚动性能的方法。通过自定义Adapter,根据不同item类型加载对应的布局,并利用viewHolder进行缓存,避免了频繁的布局充气和查找视图操作,有效提升了用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在项目中需要对listview中的数据进行分组,我构思的基本原理就是,在适配器Adapter的getView()方法中,根据当前item类型,分别加载不同的布局,这样是很容易实现的,想必大家都很清楚这个小东西。但是问题是,这样的代码写下来listview在数据很多时,上下滑动会很卡,于是乎就想到了用viewHolder来进行缓存, 难度就在对不同的item进行不同的缓存。

下面是我实现的效果:



第1、 2,3 、 4,5,6 、7、 8,9、  10,11,12......如此循环下去,下面是我实现的代码:

复写两个方法getVIewTypeCount()和getItemViewType(int position)

public class listViewTest extends Activity {  
    /** Called when the activity is first created. */  
    ListView listView;  
    MyAdapter listAdapter;  
    ArrayList<String> listString;  
      
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        listView = (ListView)this.findViewById(R.id.listview);  
        listString = new ArrayList<String>();  
        for(int i = 0 ; i < 100 ; i++)  
        {  
            listString.add(Integer.toString(i));  
        }  
        listAdapter = new MyAdapter(this);  
        listView.setAdapter(listAdapter);  
    }  
  
class MyAdapter extends BaseAdapter{  
  
    Context mContext;  
    LinearLayout linearLayout = null;  
    LayoutInflater inflater;  
    TextView tex;  
    final int VIEW_TYPE = 3;  
    final int TYPE_1 = 0;  
    final int TYPE_2 = 1;  
    final int TYPE_3 = 2;  
      
    public MyAdapter(Context context) {  
        // TODO Auto-generated constructor stub  
        mContext = context;  
        inflater = LayoutInflater.from(mContext);  
    }  
  
    @Override  
    public int getCount() {  
        // TODO Auto-generated method stub  
        return listString.size();  
    }  
  
    //每个convert view都会调用此方法,获得当前所需要的view样式  
    @Override  
    public int getItemViewType(int position) {  
        // TODO Auto-generated method stub  
        int p = position%6;  
        if(p == 0)  
            return TYPE_1;  
        else if(p < 3)  
            return TYPE_2;  
        else if(p < 6)  
            return TYPE_3;  
        else  
            return TYPE_1;  
          
    }  
  
    @Override  
    public int getViewTypeCount() {  
        // TODO Auto-generated method stub  
        return 3;  
    }  
  
    @Override  
    public Object getItem(int arg0) {  
        // TODO Auto-generated method stub  
        return listString.get(arg0);  
    }  
  
    @Override  
    public long getItemId(int position) {  
        // TODO Auto-generated method stub  
        return position;  
    }  
  
    @Override  
    public View getView(int position, View convertView, ViewGroup parent) {  
        // TODO Auto-generated method stub  
        viewHolder1 holder1 = null;  
        viewHolder2 holder2 = null;  
        viewHolder3 holder3 = null;  
        int type = getItemViewType(position);  
          
          
        //无convertView,需要new出各个控件  
        if(convertView == null)  
        {     
            Log.e("convertView = ", " NULL");  
              
            //按当前所需的样式,确定new的布局  
            switch(type)  
            {  
            case TYPE_1:  
                convertView = inflater.inflate(R.layout.listitem1, parent, false);  
                holder1 = new viewHolder1();  
                holder1.textView = (TextView)convertView.findViewById(R.id.textview1);  
                holder1.checkBox = (CheckBox)convertView.findViewById(R.id.checkbox);  
                Log.e("convertView = ", "NULL TYPE_1");  
                convertView.setTag(holder1);  
                break;  
            case TYPE_2:  
                convertView = inflater.inflate(R.layout.listitem2, parent, false);  
                holder2 = new viewHolder2();  
                holder2.textView = (TextView)convertView.findViewById(R.id.textview2);  
                Log.e("convertView = ", "NULL TYPE_2");  
                convertView.setTag(holder2);  
                break;  
            case TYPE_3:  
                convertView = inflater.inflate(R.layout.listitem3, parent, false);  
                holder3 = new viewHolder3();  
                holder3.textView = (TextView)convertView.findViewById(R.id.textview3);  
                holder3.imageView = (ImageView)convertView.findViewById(R.id.imageview);  
                Log.e("convertView = ", "NULL TYPE_3");  
                convertView.setTag(holder3);  
                break;  
            }  
        }  
        else  
        {  
            //有convertView,按样式,取得不用的布局  
            switch(type)  
            {  
            case TYPE_1:  
                holder1 = (viewHolder1) convertView.getTag();  
                Log.e("convertView !!!!!!= ", "NULL TYPE_1");  
                break;  
            case TYPE_2:  
                holder2 = (viewHolder2) convertView.getTag();  
                Log.e("convertView !!!!!!= ", "NULL TYPE_2");  
                break;  
            case TYPE_3:  
                holder3 = (viewHolder3) convertView.getTag();  
                Log.e("convertView !!!!!!= ", "NULL TYPE_3");  
                break;  
            }  
        }  
  
        //设置资源  
        switch(type)  
        {  
            case TYPE_1:  
                holder1.textView.setText(Integer.toString(position));  
                holder1.checkBox.setChecked(true);  
                break;  
            case TYPE_2:  
                holder2.textView.setText(Integer.toString(position));  
                break;  
            case TYPE_3:  
                holder3.textView.setText(Integer.toString(position));  
                holder3.imageView.setBackgroundResource(R.drawable.icon);  
                break;  
        }  
          
          
        return convertView;  
    }  
      
}  
  
  
//各个布局的控件资源  
  
class viewHolder1{  
    CheckBox checkBox;  
    TextView textView;  
}  
class viewHolder2{  
    TextView textView;  
}  
class viewHolder3{  
    ImageView imageView;  
    TextView textView;  
}  
}  

在看了AbsListView.java的源代码发现,在ObtainView()方法中,它会来判断当前litview中的type个数,也就是我复写getViewTypeCount()的原因,我们这里有三个不同的item布局,他们都被缓存了起来,所以在getview()方法中,当上下滑动时,就没有必要再重新做inflate和findViewById()的工作,直接使用回收来的viewHolder对象,大大的提高了listview滑动的流畅性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值