关于ListView自定义adapter的个人心得

       自定义的adapter通过getView()方法来向ListView提供每一个item所需要的view对象。初始时ListView会从BaseAdapter中根据当前的屏幕布局实例化一定数量的view对象,同时ListView会将这些view对象缓存起来。当向上滚动ListView时,原先位于最上面的list item的view对象会被回收,然后被用来构造新出现的最下面的list item。这个构造过程就是由getView()方法完成的,getView()的第二个形参 View convertView就是被缓存起来的list item的view对象(初始化时缓存中没有view对象则convertView是null)。

       重用缓存convertView传递给getView()方法来避免填充不必要的视图,如果我们不去使用convertView,而是每次都在getView()中重新实例化一个View对象的话,即浪费资源也浪费时间,也会使得内存占用越来越大。使用convertView回收一些布局供下面的item重构时使用,很好的解决了内存泄露(OOM--out of memory)的问题。

ViewHolder作用:

ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构,这个数据结构包含了指向我们要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById():因为太多的findViewById也会影响性能。

ViewHolder只是将需要缓存的那些view封装好,convertView的setTag才是将这些缓存起来供下次调用

下面自定义的adapter使用了convertView跟ViewHolder进行性能优化,只需稍微修改就可以使用:

private class MyCustomAdapter extends BaseAdapter {  
    
        private ArrayList mData = new ArrayList();  
        private LayoutInflater mInflater;  
    
        public MyCustomAdapter() {  
            mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
        }  
    
        public void addItem(final String item) {  
            mData.add(item);  
            notifyDataSetChanged();  
        }  
    
        @Override  
        public int getCount() {  
            return mData.size();  
        }  
    
        @Override  
        public String getItem(int position) {  
            return mData.get(position);  
        }  
    
        @Override  
        public long getItemId(int position) {  
            return position;  
        }   

        //在外面先定义,ViewHolder静态类
        static class ViewHolder
        {
           public ImageView img;
           public TextView title;
           public TextView info;
        }
        //然后重写getView
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
           ViewHolder holder;
           if(convertView == null)
           {
              holder = new ViewHolder();
              convertView = mInflater.inflate(R.layout.list_item, null);
              holder.img = (ImageView)item.findViewById(R.id.img)
              holder.title = (TextView)item.findViewById(R.id.title);
              holder.info = (TextView)item.findViewById(R.id.info);
              convertView.setTag(holder);
           }else
           {
              holder = (ViewHolder)convertView.getTag();
           }
              holder.img.setImageResource(R.drawable.ic_launcher);
              holder.title.setText("Hello");
              holder.info.setText("World");
           }
                                                                                                 
             return convertView;
       }
}

上面的adapter只适用于item只有一种模式,当有多种模式时以上会报错,需要修改其中的方法:

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

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;
}
}

        以上来自极客开源 (Gke OpenSource Code)团队菜鸟成员“紫易语风” 编码, 团队的使命是用开托性的思维写最稳定的代码,创造一流的互联网产品!

 http://114.55.36.64极客开源 (Gke OpenSource Code)团队社区地址,里面有极客开源 (Gke OpenSource Code)团队的一些开源项目分享。

转载于:https://my.oschina.net/zyyf/blog/727550

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值