最近发现每次使用ListView时代码好多重复,尤其是当多个界面模版都有使用到了填充器BaseAdapter的时候,代码重复十分严重.尤其是条目需要复用使用Holder的时候,这时需要面向Holder编程来解决这个问题.当然还有一些简单功能自己可以扩展.
好了步骤大致分4步:
1.定义BaseHolder抽象类--抽取MyBaseAdapter中的Holder
2.MyBaseAdapter抽象类--继承BaseAdapter
3.MainHolder--BaseHolder的实现类
4.MainActivity实现.
当然Holder抽取的好处在于处理多界面条目展示,如果只有一两个需要使用到填充器界面就没什么必要抽取了,毕竟抽取一个框架比较麻烦.并且代码也不少.
就使用上次的ImageLoader的案例
第一:BaseHolder抽象类
import android.content.Context;
import android.view.View;
public abstract class BaseHolder<T> {
private T data;
private View view;
public BaseHolder(Context context){
/**把这个View赋给全局,getRootView()就不来闹心了*/
this.view = getView(context);
/**convertView.setTag(holder),本身就是Holder*/
view.setTag(this);
}
/**
* 不是要给MyBaseAdapter中的getView()返回一个View么,直接给就是了.
* */
public View getRootView() {
return view;
}
/**
* 获取一个item的数据,用来给下面哥们填充去.
*
*/
public T getData(){
return data;
}
/**
* 设置数据
* */
public void setData(T data){
this.data=data;
/**既然获取到了数据,那就要把数据赋值给指定的地方*/
refreshView();
}
/**其实父类想说--我不知道你要什么布局,也不知道你想要什么样的布局控件,你只处理那些数据*/
public abstract void refreshView();
/**
* 话说要甩出个View的话也需要子类来给,因为父类也不知道子类想要的View长什么样子
* */
public abstract View getView(Context context);
}
第二:MyBaseAdapter类
import java.util.List;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
public abstract class MyBaseAdapter<T> extends BaseAdapter {
private List<T> list;
public MyBaseAdapter(List<T> list) {
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
BaseHolder<T> holder=null;
if (convertView == null) {
holder = getHolder();
}else{
//苦恼啊,谁能告诉我--为什么会报黄线,为什么要加@SuppressWarnings("unchecked")
holder = (BaseHolder<T>)convertView.getTag();
}
holder.setData(list.get(position));
//返回将xml文件转换成的view对象
return holder.getRootView();
}
/**Holder长什么样得由子类决定,因为只有子类才知道Holder的样子*/
public abstract BaseHolder<T> getHolder();
}
第三:MainHolder--数据处理
import android.content.Context;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
public class MainHoler extends BaseHolder<BeanDemo> {
private Context context;
public MainHoler(Context context) {
super(context);
// 上下文需要抽取出来给方法用
this.context = context;
}
private TextView tv;
private ImageView iv;
private DisplayImageOptions options;
// 填充数据
@Override
public void refreshView() {
// 获取一个条目数据来填充
BeanDemo demo = getData();
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.ic_launcher) // 设置图片下载期间显示的图片
.showImageForEmptyUri(R.drawable.ic_launcher)// 设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.ic_launcher)// 设置图片加载或解码过程中发生错误显示的图片
.cacheInMemory() // 设置下载的图片是否缓存在内存中
.cacheOnDisc() // 设置下载的图片是否缓存在SD卡中
.displayer(new RoundedBitmapDisplayer(20)) // 设置成圆角图片
.build();
// 图像加载程序配置
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
context).defaultDisplayImageOptions(options) // 设置默认的显示图片选择
.threadPriority(Thread.NORM_PRIORITY - 2) // 线程数量,默认5个
.denyCacheImageMultipleSizesInMemory() // 否认在内存中缓存图像多种尺寸
.discCacheFileNameGenerator(new Md5FileNameGenerator()) // 设置盘缓存文件名的生产者
.tasksProcessingOrder(QueueProcessingType.LIFO).build(); // 设置任务订单处理(队列处理类型)
ImageLoader.getInstance().init(config);
tv.setText(demo.getName());
ImageLoader.getInstance().displayImage("file:///" + demo.getUrl(), iv,
options);
}
@Override
public View getView(Context context) {
View inflate = View.inflate(context, R.layout.item_img, null);
tv = (TextView) inflate.findViewById(R.id.tv_item);
iv = (ImageView) inflate.findViewById(R.id.iv_item);
return inflate;
}
}
第四:填充ListView(MainActivity中)--其他代码就不写了,可以参考前一篇
list = getImgPathList();
lv_main = (ListView) findViewById(R.id.lv_img);
List<BeanDemo> listBean = getListBean(list);
//MyAdapter adapter = new MyAdapter(list);
MyAdapter2 adapter = new MyAdapter2(listBean);
lv_main.setAdapter(adapter);
animateFirstDisplayListener = new AnimateFirstDisplayListener();
}
class MyAdapter2 extends MyBaseAdapter<BeanDemo>{
public MyAdapter2(List<BeanDemo> list) {
super(list);
}
@Override
public BaseHolder<BeanDemo> getHolder() {
return new MainHoler(context);
}
}
/**
* 集合数据的封装
* */
public List<BeanDemo> getListBean(ArrayList<String> list){
List<BeanDemo> listBean = new ArrayList<BeanDemo>();
BeanDemo demo = null;
for (int i = 0; i < list.size(); i++) {
demo = new BeanDemo();
demo.setUrl(list.get(i));
demo.setName("条目"+i);
listBean.add(demo);
}
return listBean;
}
javaBean:
public class BeanDemo {
public String name;
public String url;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}