自定义封装了ViewHolder的BaseAdapter,简化了Adapter的编写
有过一定开发经验的Android程序员一定知道保持View对象的引用在提高ListView的性能上很有帮助,所以每次实现BaseAdapter的子类都要写个ViewHolder。如下:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//每次都要判断convertView是否存在,这样写其实很繁琐
ViewHolder viewHolder=null;
if (convertView==null){
convertView=inflater.inflate(R.layout.item_layout,parent,false);
viewHolder=new ViewHolder(convertView);
convertView.setTag(viewHolder);
}else{
viewHolder= (ViewHolder) convertView.getTag();
}
Data data=list.get(position);
//
viewHolder.textView1.setText(data.getName());
//
viewHolder.textView2.setText(data.getSex());
/**
* 适配器的引用
*/
private static class ViewHolder{
public TextView textView1;
public TextView textView2;
}
}
所以我就想了,为何不利用面向对象的思想把这份重复编写的代码给封装起来,
因为在每个Adapter的getView方法里,其主要流程是一样的:
1.判断convertView是否为空,如果convertView为空,则进行步骤2,否则进行步骤4;
2.创建一个新的view赋值给convertView;
3.为这个convertView创建一个新的ViewHolder,并设置该ViewHolder为convertView的标签;
4.获得ViewHolder,根据业务的不同使用ViewHolder里的控件引用。
其实,这些个步骤组合在一起,相当于一个模板!任何Adapter的getView()方法里都会遵循这个模板流程去执行,只是,不同的Adapter根据业务的不同,以下步骤会有所不同:步骤2,步骤3,步骤4。
这个问题是不是很熟悉,对于完成一个任务,有一样的模板,而子步骤的实现可能不一样,解决这一类的问题,通常我们可以使用"模板模式"——又叫"模板方法模式",在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情冴下,重新定义算法中的某些步骤。
在这个问题里,笔者同样采用了模板模式的思想,定义了一个 BaseMyAdapter 作为模板(抽象)类:
/**
* 封装了ViewHolder的Adapter
* Created by tzy on 2015/8/13.
*/
public abstract class BaseMyAdapter extends BaseAdapter {
public BaseMyAdapter() {}
@Override
public int getCount() {
return list.size();
}
@Override
public T getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
public static class ViewHolder {}//这个ViewHolder 主要是用来继承的
//这里是模板方法,定义了获取View的算法骨架
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//在这里BaseMyAdapter做了convertView是否复用的判断
ViewHolder viewHolder;
if(convertView == null)
{ //如果convertView 还是空的,则生成一个新的View
convertView = createView(position, convertView, parent);
//要根据convertView来获取ViewHolder对象
viewHolder = getViewHolder(convertView);
//将
convertView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
loadData(viewHolder, position, convertView, parent);
return convertView;
}
/**
*获得ViewHolde。抽象行为,放到子类去实现
* @param v
* @return
*/
public abstract ViewHolder getViewHolder(View v);
/**
*获得View。抽象行为,放到子类去实现
* @param position
* @param convertView
* @param parent
* @return
*/
public abstract View createView(int position, View convertView, ViewGroup parent);
/**
*加载数据。抽象行为,放到子类去实现
* @param viewHolder
* @param position
* @param convertView
* @param parent
*/
public abstract void loadData(ViewHolder viewHolder,int position, View convertView, ViewGroup parent);
}
然后接下来是这个模板的一个具体类:
/**
* 具体的Adapter
* Created by tzy on 2015/8/18.
*/
public class ConcreteAdapter extends BaseMyAdapter<OrderDetail.OList>{
public ConcreteAdapter () {
super();
}
//实现抽象类的方法
@Override
public ViewHolder getViewHolder(View v) {
MyViewHolder viewHolder =new MyViewHolder();
viewHolder.textPrice =(TextView)v.findViewById(R.id.textSubtotal);
viewHolder.textZone =(TextView)v.findViewById(R.id.textZone);
return viewHolder;
}
//实现抽象类的方法
@Override
public View createView(int position, View convertView, ViewGroup parent) {
return inflater.inflate(R.layout.item_olist,null,false);
}
//实现抽象类的方法
@Override
public void loadData(ViewHolder viewHolder, int position, View convertView, ViewGroup parent) {
OrderDetail.OList data = list.get(position);
MyViewHolder myViewHolder = (MyViewHolder) viewHolder;
myViewHolder.textPrice.setText("¥"+data.getSubtotal());
myViewHolder.textZone.setText(data.getZone());
}
//实现的ViewHolder
class MyViewHolder extends ViewHolder
{
public TextView textZone;
public TextView textPrice;
}
}
看吧,这样的具体的一个Adapter就很简洁了,之前写在一起的几个步骤,现在分散到子类的这些方法去实现了。子类只需要实现这些方法,就可以获取到view了,而不用在重复地写那些判断逻辑了,因为这些工作模板类已经帮我们做了!