Android之listview万能适配器

什么叫万能适配器,其实就是这种适配器是万能的,所有需要使用适配器的组件,都可用这一个适配器就行。

既然这样,就来讲讲吧

先来看看效果图:


当然了,这只是很简单的例子,很简单的布局,这里只是用来做个例子,以后也可以写别的布局,这个适配器都是适用的~

那我们就来讲讲怎么从普通的适配器到万能适配器的吧~

步骤:

1.首先普通的适配器的写法是--MyAdapter.class:

public class MyAdapter extends BaseAdapter{

	private Context context;
	private List<Bean>datas;
	LayoutInflater layoutInflater;
	int resId;//布局文件

	
	public MyAdapter(Context context, List<Bean> datas,int resId) {
		this.context = context;
		this.datas = datas;
		this.resId=resId;
		layoutInflater=LayoutInflater.from(context);
	}
	
	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return datas.size();
	}

	

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return datas.get(position);
	}

	@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
		if(convertView==null){
			convertView=layoutInflater.inflate(R.layout.listview,null);
			holder=new ViewHolder();
			holder.title=(TextView) convertView.findViewById(R.id.title);
			holder.desc=(TextView) convertView.findViewById(R.id.desc);
			holder.time=(TextView) convertView.findViewById(R.id.time);
			holder.phone=(TextView) convertView.findViewById(R.id.phone);
			convertView.setTag(holder);		
		}else{
			holder=(ViewHolder) convertView.getTag();
		}
		holder.title.setText(datas.get(position).getTitle());
		holder.desc.setText(datas.get(position).getDesc());
		holder.time.setText(datas.get(position).getTime());
		holder.phone.setText(datas.get(position).getPhone());
	}
	static class ViewHolder{
		TextView title,time,desc,phone;
	}
}
2.万能适配器的编写步骤:

(1)首先我们得分析哪些代码是不变的,哪些是可变的,这样才能确定哪些代码能够减少。

这三个重写的方法应该是不变的。

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return datas.size();
	}

	

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return datas.get(position);
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}
还有getView方法里面的一些代码:

		if(convertView==null){
			convertView=layoutInflater.inflate(R.layout.listview,null);
			holder=new ViewHolder();
			holder.title=(TextView) convertView.findViewById(R.id.title);
			holder.desc=(TextView) convertView.findViewById(R.id.desc);
			holder.time=(TextView) convertView.findViewById(R.id.time);
			holder.phone=(TextView) convertView.findViewById(R.id.phone);
			convertView.setTag(holder);		
		}else{
			holder=(ViewHolder) convertView.getTag();
		}

只不过findViewById我们需要处理一下。所以我们应该把这些不变的代码抽取出来,不应该让用户重复写这些代码。

把这些代码抽取出来,当然这些代码都应该放在ViewHolder中

(2)新建一个类 ViewHolder.java

public class ViewHolder {
	private View convertView,int mposition;
	//构造函数
	//每个convertView会绑定一个ViewHolder对象
	public ViewHolder(Context context, int mposition,View convertView,ViewGroup parent,int resId) {
		convertView=View.inflate(context, resId, null);
		this.convertView=convertView;this.mposition=mposition;
		convertView.setTag(this);
	}	
	//拿到一个ViewHolder对象
	public static ViewHolder get(Context context,int mposition,
			View convertView,ViewGroup parent,int resId){
		
		if(convertView==null){
			return new ViewHolder(context,mposition,convertView, parent, resId);
		}else {
			ViewHolder holder=(ViewHolder) convertView.getTag();
			return holder;
		}
	}	
}
传过来的参数包括:Context context, int mposition
,View convertView, ViewGroup parent, int layoutId,这些参数都是加载布局文件所需要的。

然后就是这些代码需要抽取了:

			holder.title=(TextView) convertView.findViewById(R.id.title);
			holder.desc=(TextView) convertView.findViewById(R.id.desc);
			holder.time=(TextView) convertView.findViewById(R.id.time);
			holder.phone=(TextView) convertView.findViewById(R.id.phone);
在类ViewHolder中新建方法:

	
	//泛型,返回的是View的一个子类
	//获取控件,通过控件的ID获取对应的控件,如果没有就加入mViews
	//resId是一个ID
	public <T extends View>T getView(int resId){
		View view=mViews.get(resId);
		if(view==null){
			//如果mViews没有相应的控件,我们就从convertView中找到这个控件,
			//并将这个控件和其ID存放在mViews
			view=convertView.findViewById(resId);
			mViews.put(resId, view);
		}
		return (T) view;
	}
接下来要在ViewHolder这个类的返回convertView,这个返回值就容易了,直接返回就行了

	//返回一个convertView对象
	public View getmConvertView() {
		return convertView;
	}
	

然后在MyAdapter中getView方法代码如下:

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		//2.
		ViewHolder holder=ViewHolder.get(context, position, convertView, 
				parent, resId);
		((TextView)holder.getView(R.id.title)).setText(datas.get(position).getTitle());
		((TextView)holder.getView(R.id.desc)).setText(datas.get(position).getDesc());
		((TextView)holder.getView(R.id.time)).setText(datas.get(position).getTime());
		((TextView)holder.getView(R.id.phone)).setText(datas.get(position).getPhone());
		return holder.getmConvertView();
	}

这部分工作都完了,就只留下了为组件设置数据的那段代码了,这段代码由于是可变的,应该让用户来做,所以设置为抽象方法。

(3)新建一个类 CommonAdapter.java 继承BaseAdapter:

//(把MyAdapter中的getView方法抽取出来)
public abstract class CommonAdapter<T> extends BaseAdapter{

	private Context context;
	private List<T>data;//data是不明类型的数据
	int resId;//布局文件
	public CommonAdapter(Context context,List<T>data,int resId){
		this.context=context;
		this.resId=resId;
		this.data=data;
	}
	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return data.size();
	}

	//通过查看源代码发现,getItem方法不是在Baseadapter类中被调用的,而是在Adapterview中被调用的。
	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return data.get(position);
	}

	@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
		ViewHolder holder=ViewHolder.get(context, position, convertView, parent, resId);
		current(holder,getItem(position));//把那个getView方法抽取出来
		return holder.getmConvertView();
	}
	public abstract void current(ViewHolder holder,Object object);
}
然后有这些代码还不行~还要实现那个抽象方法~

所以新建一个 Adapter 继承 CommonAdapter-MagicAdapter:

public class MagicAdapter extends CommonAdapter<Bean>{

	//resId是布局文件,调用基类的构造方法
	public MagicAdapter(Context context, List<Bean> data, int resId) {
		super(context, data, resId);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void current(ViewHolder holder, Object object) {
		// TODO Auto-generated method stub
		Bean bean=(Bean)object;
		((TextView)holder.getView(R.id.title)).setText(bean.getTitle());
		((TextView)holder.getView(R.id.desc)).setText(bean.getDesc());
		((TextView)holder.getView(R.id.phone)).setText(bean.getPhone());
		((TextView)holder.getView(R.id.time)).setText(bean.getTime());
	}

}
然后在MainActivity为listview加载适配器

listview.setAdapter(new MagicAdapter(MainActivity.this, datas,R.layout.listview));
核心代码如下:

MainActivity:

public class MainActivity extends Activity {
    private ListView listview;
    private List<Bean>datas;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initData();
		initView();

	}
	//初始化数据
	public void initData() {
		// TODO Auto-generated method stub
		datas=new ArrayList<Bean>();
		for(int i=1;i<10;i++){
			Bean bean=new Bean("Android新技能"+i, "Android打造万能适配器", "2016-5-20", "10086");
			datas.add(bean);
		}
	}
	//初始化控件
	public void initView() {
		// TODO Auto-generated method stub
		listview=(ListView) findViewById(R.id.listview);
		//1.
		//listview.setAdapter(new MyAdapter(MainActivity.this, datas));
		//2.调用这个适配器,把数据加载出来
		listview.setAdapter(new MagicAdapter(MainActivity.this, datas,R.layout.listview));
	}

	
}
Bean:

public class Bean {

	String title,desc,time,phone;

	public Bean(String title, String desc, String time, String phone) {
		super();
		this.title = title;
		this.desc = desc;
		this.time = time;
		this.phone = phone;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	public String getTime() {
		return time;
	}

	public void setTime(String time) {
		this.time = time;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}
}
源码: 下载


































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值