利用Android反射與泛型機制寫一個通用的Adapter類
阿新 • • 發佈:2019-01-23
注意點:Android的反射機制有一個問題,就是Class.getDeclaredFields()返回的變數陣列與我們定義的類的變數順序是不一致的.Android是經過了字母順序排序的.所以我們需要將變數名傳入adapter
//定義一個帶泛型的抽象類作為基類,T表示資料類,E表示ViewHolder類 public abstract class TBaseAdapter<T> extends BaseAdapter{ List<T> mList;//用於存放資料集 LayoutInflater mInflater; Context context; int [] viewIds;//存放控制元件ID String[] fields;//存放ViewHolder類變數的名字 int layoutId;//佈局檔案ID Class<?> classOfE;//ViewHolder類 //建構函式 public TBaseAdapter(Context context, List<T> mList) { // TODO Auto-generated constructor stub mInflater = LayoutInflater.from(context); this.mList = mList; this.context = context; } public void setFields(String[] fields) { this.fields = fields; } public void setViewIds(int[] viewIds){ this.viewIds = viewIds; } public void setClass(Class<?> e){ this.classOfE = e; } public void setLayoutId(int layoutId) { this.layoutId = layoutId; } @Override public int getCount() { // TODO Auto-generated method stub return mList == null ? 0 : mList.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return mList.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } //獲取佈局檔案,將控制元件初始化 public Object initViewHolder(View convertView){ try { if (fields.length != viewIds.length) { return null; } Object e = classOfE.newInstance();//呼叫空建構函式 int length = fields.length; for(int i = 0;i<length;i++){ Field field = classOfE.getDeclaredField(fields[i]);//通過反射獲取變數 field.setAccessible(true);//將變數設定為可訪問狀態 field.set(e,convertView.findViewById(viewIds[i]));//為變數設值 } return e; } catch (InstantiationException ex) { // TODO Auto-generated catch block ex.printStackTrace(); return null; } catch (IllegalAccessException ex) { // TODO Auto-generated catch block ex.printStackTrace(); return null; } catch (IllegalArgumentException ex) { // TODO Auto-generated catch block ex.printStackTrace(); return null; } catch (NoSuchFieldException e1) { // TODO Auto-generated catch block e1.printStackTrace(); return null; } } //抽象方法,實現些方法用於數集的繫結 public abstract void addDataToView(T t,Object o); @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub Object e = null; if (convertView == null) { convertView = mInflater.inflate(layoutId, null); e =initViewHolder(convertView); if (e!=null) convertView.setTag(e); } else e = convertView.getTag(); addDataToView(mList.get(position),e); return convertView; } }
這樣以後寫Adapter的時候,只要繼承這個類,並實現addDataToView()
方法就可以.然初始化adapter後,傳入相應的佈局檔案ID,控制元件ID,變數名和ViewHolder類就可以.如下:
Adapter adapter = new Adapter(this, mList);
adapter.setLayoutId(R.layout.item);
int[] ids = {R.id.name,R.id.age,R.id.sex};
String[] fields = {“name”,”age”,”sex”};
adapter.setClass(MyViewHolder.class);
adapter.setViewIds(ids);
adapter.setFields(fields);