Android通用适配器CommonAdapter

本文介绍了一种在Android开发中提高效率的方法——通过创建通用适配器CommonAdapter减少重复代码。具体步骤包括抽象出视图展示逻辑、设计转换器类Convertor以及实现具体的Adapter子类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android通用适配器CommonAdapter

1、刚完成一个小项目,项目中有多个页面,其中包含了许多ListView和GridView,避免不了要写很多的Adapter,当时就像那么多重复的代码,若是抽取一下就好了,由于时间紧迫,没有来得及抽取,刚好前几天看到慕课上《打造万能适配器》,本文算是对该视频的学习记录,按照自己的方式,对视频中的代码进行了稍稍的改动,废话说多了,下面进入主题…
2、Demo源码:http://download.youkuaiyun.com/detail/gonghao2014/9704384

1、普通方式

注:这里只给出关键部分代码

//类似ListView这样的视图,继承BaseAdapter实现ListView的适配器类
public class ListViewAdapter extends BaseAdapter {
    private Context mContext;
    private List<Bean> mBeans;
    public ListViewAdapter(Context context, List<Bean> beans) {
        this.mContext = context;
        this.mBeans = beans;
    }

    @Override
    public int getCount() {
        return mBeans.size();
    }

    @Override
    public Object getItem(int position) {
        return mBeans.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(
                    R.layout.item_grid_view, parent, false);
        }
        ViewHolder viewHolder = (ViewHolder) convertView.getTag();
        if (viewHolder == null) {
            viewHolder = new ViewHolder();
            convertView.setTag(viewHolder);
        }
        viewHolder.img = (ImageView) convertView.findViewById(R.id.id_img);
        viewHolder.title = (TextView) convertView.findViewById(R.id.id_title);
        Bean bean = mBeans.get(position);
        viewHolder.img.setImageResource(bean.getImgId());
        viewHolder.title.setText(bean.getTitle());
        return convertView;
    }
    class ViewHolder {
        ImageView img;
        TextView title;
    }
}
//当一个项目中类似这样的ListView和GridView多了以后,会发现要写很多个Adapter类,并且代码很多是重复的
//比如说:Context字段、List<Bean>实体数据字段、构造方法、getCount()、getItem()、getItemId()

1、仔细观察后发现,其实每个Adapter类中,最大的不同点就是用户看到的视图(childView),和视图中填充的数据
2、所以就想,能抽象一个转化方法–convert(视图Id,该视图的显示数据)
3、两个参数:视图Id(viewId)该视图要显示的数据(bean.getXX())
4、写一个抽象类CommonAdapter,让需要使用的Adapter继承CommonAdapter类,重写其中的convert方法即可

2、抽取方式

第一步:新建一个CommonAdapter类,代码如下

/**
 * 通用适配器类
 * @author HaoG
 * @param <T>
 *            要填充的数据类型
 */
public abstract class CommonAdapter<T> extends BaseAdapter {

    private Context mContext; //上下文对象,LayoutInflater加载布局时用到
    private List<T> mBeans; //视图要显示的数据的集合
    private int mLayoutId; //要显示的视图所在的布局的ID

    public CommonAdapter(Context context, List<T> beans, int layoutId) {
        this.mContext = context;
        this.mBeans = beans;
        this.mLayoutId = layoutId;
    }

    @Override
    public int getCount() {
        return mBeans.size();
    }

    @Override
    public Object getItem(int position) {
        return mBeans.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(mLayoutId,
                    parent, false);
        }
        //这里是一个转换器类,下面详细介绍
        Convertor convertor = Convertor.get(convertView);
        //根据上面的想法,抽取出来的抽象方法convert()
        convert(convertor, mBeans.get(position));
        return convertView;
    }

    /**
     * 使用转换器convertor,将数据bean显示在相对应View上
     * 具体的视图和数据的适配依据需求而定,所以具体的实现要交个子类去实现
     * @param convertor
     * @param bean
     */
    public abstract void convert(Convertor convertor, T bean);
}

第二步:新建一个Convertor类,代码如下

/**
 * 转换器类 封装了一个ViewHolder(即mViews)
 * 
 * @author HaoG
 */
public class Convertor {

    private View mConvertView;
    private SparseArray<View> mViews;// viewHolder

    public Convertor(View convertView) {
        mViews = new SparseArray<View>();
        this.mConvertView = convertView;
    }

    /**
     * 获取convertor实例
     * 
     * @param convertView
     * @return
     */
    public static Convertor get(View convertView) {
        Convertor convertor = (Convertor) convertView.getTag();
        if (convertor == null) {
            convertor = new Convertor(convertView);
            convertView.setTag(convertor);
        }
        return convertor;
    }

    /**
     * 根据viewId获取View视图实例
     * 
     * @param viewId
     * @return
     */
    @SuppressWarnings("unchecked")
    private <T extends View> T getView(int viewId) {
        View childView = mViews.get(viewId);
        if (childView == null) {
            childView = mConvertView.findViewById(viewId);
            mViews.put(viewId, childView);
        }
        return (T) childView;

    }

    /**
     * 给指定viewId的TextView控件设置文本
     * 
     * @param viewId
     * @param text
     * @return
     */
    public Convertor setText(int viewId, String text) {
        TextView tv = getView(viewId);
        tv.setText(text);
        //返回值是Convertor类的对象本身是为了代码的书写方便,可以链式书写,下面可以看到链式书写形式
        return this;
    }

    /**
     * 给指定viewId的ImageView控件设置图片
     * 
     * @param viewId
     * @param imgId
     * @return
     */
    public Convertor setImageResource(int viewId, int resId) {
        ImageView iv = getView(viewId);
        iv.setImageResource(resId);
        return this;
    }

    // PS:
    // 类似setText(),setImageResource()方法,可根据需求自行添加
    // 如Item视图中含有RadioButton控件,那个可以添加setChecked()方法

}

第三步:根据业务需求,新建一个CommonAdapter的子类–ListViewAdapter类,代码如下

/**
 * ListView适配器类
 * 
 * @author HaoG
 *
 */
public class ListViewAdapter3 extends CommonAdapter<ListBean> {

    public ListViewAdapter3(Context context, List<ListBean> beans, int layoutId) {
        super(context, beans, layoutId);
    }
    /**
     * 1、在这里我们可以看到子类中只需要实现其convert()方法即可
     * 2、在Convertor类中,已经封装的相关的接口,在这里直接调用即可
     */
    @Override
    public void convert(Convertor convertor, ListBean bean) {
        convertor.setImageResource(R.id.id_img, bean.getImgId())
                .setText(R.id.id_title, bean.getTitle());
    }
}

3、结语

1、到这里基本就结束了,如果有不太懂的地方,可以去慕课,观看《打造Android万能适配器》
2、这里并不是打广告,我也是Android初学者,在写项目时多个Adapter感到繁琐,刚好碰到这个通用的CommonAdapter,便记录下学习小结,愿与君共进步…
3、感谢《慕课网–打造万能适配器》

CommonAdapter 一个适用于ListView/GridView/RecyclerView的Adapter库,简化大量重复代码,支持多种布局,可自定义图片加载的实现。功能特点:简化大量重复代码支持多布局自定义图片加载常用数据操作view复用RecyclerView item 点击和长按事件gradle依赖dependencies {     compile 'com.classic.adapter:commonadapter:1.0'     //项目中使用到RecyclerView,需要添加依赖     compile 'com.android.support:recyclerview-v7:23.2.0'}ListView/GridView 使用示例:List<News> newsList = ...; //单布局文件 listView = (ListView) findViewById(R.id.listview); listView.setAdapter(new CommonAdapter<News>(context,     //item布局文件     R.layout.item_none_picture, newsList ) {     @Override public void onUpdate(BaseAdapterHelper helper, News item) {         //BaseAdapterHelper详细用法,见下方         helper.setText(R.id.xxx, item.getTitle())                //可实现ImageLoad接口,进行图片自定义加载方式,demo里面使用的Glide               .setImageLoad(new GlideImageLoad())               .setImageUrl(R.id.xxx,item.getCoverUrl());     } }); //多布局文件 private final class MultipleLayoutAdapter extends CommonAdapter<News>{     public MultipleLayoutAdapter(Context context, int layoutResId, List<News> data) {         super(context, layoutResId, data);     }     //多种布局重写此方法即可     @Override public int getLayoutResId(News item) {         int layoutResId = -1;         switch (item.getNewsType()){             case News.TYPE_NONE_PICTURE: //布局样式一                 layoutResId = R.layout.item_none_picture;                 break;             case News.TYPE_SINGLE_PICTURE: //布局样式二                 layoutResId = R.layout.item_single_picture;                 break;             case News.TYPE_MULTIPLE_PICTURE: //布局样式三                 layoutResId = R.layout.item_multiple_picture;                 break;             更多的布局样式 ...         }         return layoutResId;     }     @Override public void onUpdate(BaseAdapterHelper helper, News item) {         helper.setImageLoad(new GlideImageLoad());         switch (item.getNewsType()){             case News.TYPE_NONE_PICTURE: //布局样式一                 helper.setText(R.id.xxx, item.getTitle())                       .setImageUrl(R.id.xxx,item.getCoverUrl());                 break;             case News.TYPE_SINGLE_PICTURE: //布局样式二                 helper.setText(R.id.xxx, item.getTitle())                       .setImageUrl(R.id.xxx,item.getCoverUrl());                 break;             case News.TYPE_MULTIPLE_PICTURE: //布局样式三                 helper.setText(R.id.xxx, item.getTitle())                       .setImageUrl(R.id.xxx,item.getCoverUrl());                 break;             更多的布局样式 ...         }     } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值