万能适配器

背景#

,重构公司项目时优化 做个记录.以后用得到

没有废话,直接代码

像这样 ,BaseCommAdapter也是继承自BaseAdapter,传入一个泛型T表示需要绑定的JavaBean。外部通过构造器传入需要展示在listview中的JavaBean的数据集合就可以轻松实现数据的绑定并显示,有几个方法没必要每次都需要子类来实现,我们将它们封装到BaseCommAdapter中。


/**
 *  @author Town
 *  @created at 2017/11/20 11:45
 *  @Last Modified by: Town
 *  @Last Modified time: 2017/11/20 11:45
 *  @Remarks 万能适配器
 */
public abstract class BaseCommAdapter<T> extends BaseAdapter {
    private List<T> mDatas;

    public BaseCommAdapter(List<T> datas) {
        mDatas = datas;
    }

    @Override
    public int getCount() {
        return mDatas == null ? 0 : mDatas.size();
    }

    @Override
    public T getItem(int position) {
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position)
    {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = ViewHolder
                .newsInstance(convertView, parent.getContext(), getLayoutId());
        setUI(holder,position,parent.getContext());
        return holder.getConverView();
    }

    /**
     * 设置UI
     * @param holder
     * @param position
     * @param context
     */
    protected abstract void setUI(ViewHolder holder, int position, Context context);

    /**
     * 设置布局
     * @return
     */
    protected abstract int getLayoutId();
}

说说getview方法,通过ViewHolder的静态方法newsInstance创建一个viewholder实例,需要传入三个参数,分别是convertView,上下文对象,以及item的布局id(由于布局id并不是一成不变的,我们抽成一个getLayoutId()的抽象方法让子类实现),setUI()用来执行UI的显示设置。注意,convertView已经保存在viewholder中了,所以我们只需要从中取出再返回就可。

我们把子类特有的行为,比如item布局id,ui的设置方法都抽离出getview封装成抽象方法,子类就可以不用再去重写getview方法。

这样BaseAdapter的四个抽象方法都被我们封装到BaseCommAdapter中了。

ViewHolder复用

在构造方法中,首先先加载布局文件到mConvertView,并把当前的viewholder对象设置为tag。

同时我们使用用了一个稀疏数组SparseArray来保存mConvertView中的节点view,它是谷歌在utils包中提供的一个工具类,效果类似于一个key为integer值为object的map集合,但是性能比map要好。mViews的key就是节点view的id。


/**
 * @author Town
 * @created at 2017/11/20 11:50
 * @Last Modified by: Town
 * @Last Modified time: 2017/11/20 11:50
 * @Remarks 万能适配器之ViewHolder
 */
public class ViewHolder {

    /**
     * 保存所有itemview的集合
     */
    private SparseArray<View> mViews;

    private View mConvertView;

    private ViewHolder(Context context, int layoutId) {
        mConvertView = View.inflate(context, layoutId, null);
        mConvertView.setTag(this);
        mViews = new SparseArray<>();
        UIUtils.auto(mConvertView);//适配布局
    }

    public static ViewHolder newsInstance(View convertView, Context context, int layoutId) {
        if (convertView == null) {
            return new ViewHolder(context, layoutId);

        } else {
            return (ViewHolder) convertView.getTag();
        }
    }

    /**
     * 获取根view
     *
     * @return
     * @author Town
     * @date 2017/11/20 11:50
     */
    public View getConverView() {
        return mConvertView;
    }

    /**
     * 获取节点view
     *
     * @param id
     * @return
     * @author Town
     * @date 2017/11/20 11:50
     */
    @SuppressWarnings("unchecked")
    public <T extends View> T getItemView(int id) {
        View view = mViews.get(id);
        if (view == null) {
            view = mConvertView.findViewById(id);
            mViews.append(id, view);
        }
        return (T) view;
    }

}


使用方法

  1. 继承自我们的万能适配器

class DeliveryAdapter  extends BaseCommAdapter<JavaBean>{
     DeliveryAdapter(List<JavaBean> datas) {
        super(datas);
    }

    @Override
    protected void setUI(ViewHolder holder, int position, Context context) {
       
    }

    @Override
    protected int getLayoutId() {
        return R.layout.item_delivery;
    }
    }

  1. 当正常适配器使用即可

我只是做个记录