转载

ListView的深入学习

ListView通常有两个职责:

将数据填充到布局 ; 处理用户的点击选择操作

二。创建ListView需要3个元素

ListView的每一列的View

View的数据或者图片

连接数据与ListView的Adapter

三。常用的适配器

Adapter

含义

ArrayAdapter<T>

用来绑定一个数组,支持泛型操作

SimpleAdapter

用来绑定在xml中定义的控件对应的数据

SimpleCursorAdapter

用来绑定游标得到的数据

BaseAdapter

通用的基础适配器

四,ArrayAdapter

代码:

String[] str=new String[]{"1","2","3"};

lv.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,str) );

五。SimpleAdapter

代码:

ArrayList<HashMap<String,Object> >  listItem=new ArrayList<HashMap<String,Object> >();

for(int i=0;i<10,i++){

HashMap<String ,Object>  map=new HashMap<String,Object>();

map.put("ItemImage",R.drwaable.icon);

map.put("ItemTitle","第"+i+“行”);

map.put("ItemText",i+"行");

listItem,add(map);

}

//this,存放的数据,每一行的布局,动态数组中的数据源的键对应到布局view中

SimpleAdapter  smadapter=new SimpleAdapter(this,listItem,R.layout.item,

new String[]{" ItemImage","ItemTitle","ItemText"}

new int[]{R.id.ItemImage,R.id.ItemTitle,R.id.ItemText});

lv.setAdapter(smadapter);

主意:使用SimpleAdapter一般都是用HashMap构成的列表,列表的每一节对应LisView的每一行。通过SimpleAdapter的构造函数,将HashMap的每个键的数据映射到布局文件的控件上

六。BaseAdapter

在ListView的使用中,还需要加入按钮等空间,实现单独的操作,用SimpleAdapter无法获取焦点,点击操作会被ListView的item覆盖,所以用到来Baseadapter。

使用BaseAdapter必须写一个类来继承它,以为它是一个抽象类,重写4个方法,最重要的方法是getView();

当开始绘制ListView的时候,首先调用getCount()方法,得到它的返回值,即listView的长度;

然后调用getView()方法,根据长度逐一绘制ListView的每一行;

然后getItem()和getItemId()在需要处理和取得Adapter中的数据时调用

代码:

//创建MyApdater继承BaseAdapter

MyAdapter mAdapter=new MyAdapter(this);

lv.setAdapter(mAdapter);

lv.setOnItemClickListener(new OnItemClickListener(){

public void onItemClick(AdapterView<?>arg0,View arg1,int arg2,long arg3){

log.v("你点击了"+arg2);

}

});

//方法:得到数据

private ArrayList<HashMap<String,Object> >getDate(){

ArrayList<HashMap<String,Object> >  listItem=new  ArrayList<HashMao<String,Object> >();

//为动态数组添加数据

for(int i=0,i<10,i++){

HashMap<String ,Object> map=new HashMap<String,Object>();

map.put("ItemTitle","第"+i+"行");

map.pt("ItemText","第'+i+"行");

listItem.add(map);

}

return listItem;

}

//BaseAdapter的实体类MyAdapter

private class MyAdapter extends BaseAdpater{

//得到一个LayoutInfalter对象来导入布局

private LayoutInflater mInflater;

public MyAdapter(Context context){

this.mInflater=LayoutInflater.from(context);

}

// 重写的方法

public int getCount(){

return getDate().size();  //返回数组的长度

}

public Object getItem(int position){

return null;

}

public long getItemId(int position){

return 0;

}

//重写最重要的方法

pubic View getView(final int position,View convertView,ViewGroup parent){

ViewHolder holder;

//观察convertView随listVIew的滚动情况

Log.v("my","getView"+position+"---"+convertView);

if(convertView==null){

convertView=nInflater.inflate(R.layout.item,null);

holder=new ViewHolder();

// 实力化控件

holder.title=(TextView)convertVIew.finViewByid(R.id.xxx);

holder.text=(TextView)convertVIew.finViewByid(R.id.xxx);

holder.tbutton=(Button)convertVIew.finViewByid(R.id.xxx);

convertView,setTag(holder); //绑定ViewHolder对象

}else{

//取出ViewHolder对象,ViewHolder在下面有定义

holder=(ViewHolder)contretView.getTag();

//设置TextVIew显示的内容,即我们存放在动态数组中的数据

holder.title.setText(getDate().get(position).get("ItemTitle").toString());  holder.text.setText(getDate().get(position).get("ItemText").toString());  /*为Button添加点击事件*/     holder.bt.setOnClickListener(new OnClickListener() {   @Override   publicvoid onClick(View v) {   Log.v("MyListViewBase", "你点击了按钮" + position);        //打印    Button的点击信息        }  }); 

return convertView;

}

}

//存放数据的ViewHolder

public final class ViewHolder{

public TextView title;

public TextView text;  

public Button bt;

}

}

ListView的深入学习

主意:

代码中getView()方法不容易理解。其实完全可以不用所谓的convertView和ViewHolder,直接导入布局并且设置控件显示的内容就可以了。但是这意味着有多少行数据就需要绘制多少行ListView,这显然是不可取的。这里采用了一种优化的方法。代码中,在getView()方法中加入了一行log输出convertView的内容。

从图4-38中可以看出,当启动Activity呈现第一屏ListView的时候,convertView为零。当用户向下滚动ListView时,上面的条目变为不可见,下面出现新的条目。这时候convertView不再为空,而是创建了一系列的convertView的值。当又往下滚一屏的时候,发现第11行的容器用来容纳第22行,第12行的容器用来容纳第23行。也就是说convertView相当于一个缓存,开始为0,当有条目变为不可见,它缓存了它的数据,后面再出来的条目只需要更新数据就可以了,这样大大节省了系统资料的开销。

还可以继续优化。虽然重复利用了已经绘制的view,但是要得到其中的控件,需要在控件的容器中通过findViewById的方法来获得。如果这个容器非常复杂,这显然会增加系统资源的开销。在上面的例子中,引入了Tag的概念。或许不是最好的办法,但是它确实能使ListView变得更流畅。代码中,当convertView为空时,用setTag()方法为每个View绑定一个存放控件的ViewHolder对象。当convertView不为空,重复利用已经创建的view的时候,使用getTag()方法获取绑定的ViewHolder对象,这样就避免了findViewById对控件的层层查询,而是快速定位到控件。

正文到此结束
Loading...