之前老是會寫一大堆的適配器來知足各類需求,總是重複這種坑爹的工做真是讓人煩不勝煩。不過,如今小夥伴們有福了,下面就讓萬能適配器閃亮登場吧。java
小夥伴們都知道繼承 BaseAdapter 的適配器通常是在 public View getView(int position, View convertView, ViewGroup parent) 裏面處理數據的顯示,並且通常會用 ViewHolder,進行一些性能優化,減小一些沒必要要的重複操做。本文的適配器也是在此基礎上經過抽象的方法處理顯示上的不一樣,使用的時候只要重寫此方法就好了。android
處理不一樣的數據關鍵是對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 SparseArray<View> mViews; private CommonViewHolder(Context context, LayoutInflater inflater, int resource, ViewGroup parent){ mViews = new SparseArray<View>(); 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 extends View> 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 的地方經過獲取到ide
的 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 CommonAdapter<T> extends BaseAdapter{ private LayoutInflater mInflater; private List<T> mDatas;//源數據 private int mResource;//資源文件 private Context mContext; public CommonAdapter(Context context, int resource, List<T> 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); }
具體的使用以下:優化
List<String> list = new ArrayList<String>(); list.add("bauble"); list.add("Allorry"); list.add("Allotory"); list.add("boolbe"); CommonAdapter<String> adapter = new CommonAdapter<String>(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 中要有處理數據顯示的方法,小夥伴們還能夠寫出其餘方法,如設置圖片的背景等。this