以前总是会写一大堆的适配器来满足各种需求,老是重复这种坑爹的工作真是让人烦不胜烦。不过,现在小伙伴们有福了,下面就让万能适配器闪亮登场吧。
小伙伴们都知道继承 BaseAdapter 的适配器一般是在 public View getView(int position, View convertView, ViewGroup parent) 里面处理数据的显示,而且一般会用 ViewHolder,进行一些性能优化,减少一些不必要的重复操作。本文的适配器也是在此基础上通过抽象的方法处理显示上的不同,使用的时候只要重写此方法就行了。
处理不同的数据关键是对ViewHolder类的处理。下面是ViewHolder的具体代码:
import android.content.Context;import android.util.SparseArray;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.Button;import android.widget.TextView; public class CommonViewHolder { //一个item的view,是getView(int position, View convertView, ViewGroup parent)返回的View private View mConvertView; //存一个item里面的所有View private SparseArraymViews; private CommonViewHolder(Context context, LayoutInflater inflater, int resource, ViewGroup parent){ mViews = new SparseArray (); mConvertView = inflater.inflate(resource, parent, false); mConvertView.setTag(this); } public static CommonViewHolder getViewHolder(Context context, LayoutInflater inflater, View convertView, int resource, ViewGroup parent){ if(convertView == null) return new CommonViewHolder(context, inflater, resource, parent); return (CommonViewHolder) convertView.getTag(); } /** * 根据id获取View * @param id * @return */ @SuppressWarnings("unchecked") public T getView(int id) { View view = mViews.get(id); if (view == null) { view = mConvertView.findViewById(id); mViews.put(id, view); } return (T) view; } /** * 根据id 设置TextView,Button的Text * @param viewId * @param text * @return */ public CommonViewHolder setText(int viewId, String text) { View view = getView(viewId); if (view instanceof TextView) { final TextView textView = (TextView) view; textView.setText(text); } else if (view instanceof Button) { final Button btn = (Button) view; btn.setText(text); } return this; } public View getConvertView() { return mConvertView; }}
适配器的 getView 方法获取到 ViewHolder 后通过抽象方法 setViewValue 传出,在外部用 Adapter 的地方通过获取到
的 ViewHolder 处理数据的显示。
import java.util.List;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter; public abstract class CommonAdapterextends BaseAdapter{ private LayoutInflater mInflater; private List mDatas;//源数据 private int mResource;//资源文件 private Context mContext; public CommonAdapter(Context context, int resource, List datas){ mInflater = LayoutInflater.from(context); this.mContext = context; this.mDatas = datas; this.mResource = resource; } @Override public int getCount() { if(mDatas != null) return mDatas.size(); return 0; } @Override public long getItemId(int position) { return position; } @Override public T getItem(int position) { return mDatas.get(position); } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub CommonViewHolder viewHolder = CommonViewHolder.getViewHolder(mContext, mInflater, convertView, mResource, parent); setViewValue(viewHolder, getItem(position)); return viewHolder.getConvertView(); } /** * 抽象方法,必须实现,在外面填充数据显示 * @param viewHolder * @param item * @param position */ public abstract void setViewValue(CommonViewHolder viewHolder, T item);}
具体的使用如下:
Listlist = new ArrayList (); list.add("bauble"); list.add("Allorry"); list.add("Allotory"); list.add("boolbe"); CommonAdapter adapter = new CommonAdapter (this, R.layout.item, list) { @Override public void setViewValue(CommonViewHolder viewHolder, String item) { // TODO Auto-generated method stub viewHolder.setText(R.id.name, item); } };
总结一下,此适配器的难点是 ViewHolder 类的处理,要充分利用 convertView.setTag(ViewHolder holder) 与 convertView.getTag()方法,由于ViewHolder 里面已经有convertView,所以 ViewHolder 中要有处理数据显示的方法,小伙伴们还可以写出其他方法,如设置图片的背景等。