利用Android反射与泛型机制写一个通用的Adapter类

注意点: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);

猜你喜欢

转载自blog.csdn.net/zxb3121999/article/details/46777569
今日推荐