ListView是Android中常用的重要组件之一,基本上所有软件基本都会使用ListView,所以要对ListView非常熟悉。

先看看程序效果图:

Android学习笔记:ListView及BaseAdapter使用_第1张图片

ListView的样式很多,有纯文字型,带图片显示,带按钮的等等。本次演示一个带图片的ListView。

①布局文件:

在ListView程序中,布局文件相比其他普通控件会多出至少一个,其原因是还需要一个关于ListView里面内容条目的布局文件。

内容条目的布局文件 listview_item.xml :



    
    

    
    
    
    

看了代码应该就明白了我上面说的ListView内容条目的布局指的就是

wKiom1VapkfxLmTcAAAngv935pg299.jpg这样一条条的布局文件


另外一个布局文件,整个android程序的总体布局文件 activity_main.xml :


    
    
        
        
        
    

只有一个 其中scrollbars="vertical"意思是如果条目很多,滚动时会滚动条是垂直的。


②Android代码


MainActivity.java

package com.example.testlistview;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.widget.SimpleAdapter;
/**
 * 注意继承的是ListActivity
 * @author jam
 *
 */
public class MainActivity extends ListActivity {
	
	private List> list;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		list = new ArrayList>();
		Map map1 = new HashMap();
		Map map2 = new HashMap();
		Map map3 = new HashMap();
		
		//三项,分别是图片,大标题,内容
		map1.put("avatar", R.drawable.add_option);
		map1.put("user_name", "zhangsan");
		map1.put("user_ip", "192.168.1.0");
		
		map2.put("avatar", R.drawable.add_pic);
		map2.put("user_name", "lisi");
		map2.put("user_ip", "192.168.1.1");
		
		map3.put("avatar", R.drawable.ic_launcher);
		map3.put("user_name", "wangwu");
		map3.put("user_ip", "192.168.1.2");

		list.add(map1);
		list.add(map2);
		list.add(map3);

		//使用SimpleAdapter的方法
		/**
		 * 四个参数
		 * 第一个参数是当前的Context
		 * 第二个参数,是数据来源list
		 * 第三个第四个相当于键值对的关系
		 */
/*		setListAdapter(new SimpleAdapter(getApplicationContext(), list,
				R.layout.listview_item, 
				new String[] {"user_name", "user_ip"},
				new int[] {R.id.id_tv_title, R.id.id_tv_desc}));*/
		
		//设置Adapter
		setListAdapter(new MyBaseAdapter(getApplicationContext(), list));
		
	}

}


其中MyBaseAdapter.java代码:

package com.example.testlistview;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * 继承BaseAdapter
 * 相对于SimpleAdapter来说显得麻烦,但带来了更多好处
 * @author jam
 *
 */
public class MyBaseAdapter extends BaseAdapter {

	private LayoutInflater myInfalater; 
	private List> list;
	
	public MyBaseAdapter(Context context, List> list) {
		super();
		this.list = list;
		myInfalater = LayoutInflater.from(context);
	}

	
	@Override
	public int getCount() {
		return list.size();
	}

	@Override
	public Object getItem(int position) {
		return position;
	}

	@Override
	public long getItemId(int positionId) {
		return positionId;
	}

	//重要的重写方法
	@Override
	public View getView(int position, View convertView, ViewGroup viewGroup) {
		ViewHolder viewHolder;
		if(convertView == null) {
			convertView = myInfalater.inflate(R.layout.listview_item, null);
			viewHolder = new ViewHolder();
			viewHolder.avatar = (ImageView) convertView.findViewById(R.id.id_p_w_picpathview);
			viewHolder.title = (TextView) convertView.findViewById(R.id.id_tv_title);
			viewHolder.desc = (TextView) convertView.findViewById(R.id.id_tv_desc);
			convertView.setTag(viewHolder);
		} else {
			viewHolder = (ViewHolder) convertView.getTag();
		}
		
		viewHolder.avatar.setBackgroundResource((Integer) list.get(position).get("avatar"));
		viewHolder.title.setText((CharSequence) list.get(position).get("user_name"));
		viewHolder.desc.setText((CharSequence) list.get(position).get("user_ip"));
		
		return convertView;
	}

	private class ViewHolder {
		ImageView avatar;
		TextView title;
		TextView desc;
	}
	
}


说明


BaseAdapter是一个很常用的Adapter,是一个抽象类,需要重写很多方法。

在Adapter中先调用getCount()方法,得到ListView的长度,根据这个长度逐一绘制ListView的每一行

onvertView相当于一个缓存,开始为0,当有条目变为不可见,它缓存了它的数据,后面再出来的条目只需要更新数据就可以了,这样大大节省了系统资料的开销


ViewHolder的应用 :


View的findViewById()方法也是比较耗时的,因此需要考虑只调用一次,之后就用convertView.getTag();方法来获得ViewHolder对象。 


通俗的说,inflate就相当于将一个xml中定义的布局找出来.


因为在一个Activity里如果直接用findViewById()的话,对应的是setConentView()的那个layout里的组件.


因此如果你的Activity里如果用到别的layout,比如对话框上的layout,你还要设置对话框上的layout里的组件(像图片ImageView,文字TextView)上的内容,你就必须用inflate()先将对话框上的layout找出来,然后再用这个layout对象去找到它上面的组件。


另外这里有些BaseAdapter相关资料:

http://www.open-open.com/lib/view/open1339485728006.html

http://android.tgbus.com/Android/tutorial/201104/348009.shtml