安卓万能适配器-CommonAdapter

依赖:recyclerview+glide图片加载器

compile 'com.android.support:recyclerview-v7:25.3.1'
compile 'com.github.bumptech.glide:glide:4.0.0'

这里写图片描述

1、ListView、GridView等适配器

CommonAdapter

public abstract class CommonAdapter<T> extends BaseAdapter {

    //关联的布局
    protected LayoutInflater mInflater;
    //上下文
    protected Context mContext;
    //数据源
    protected List<T> mDatas;
    protected final int mItemLayoutId;

    public CommonAdapter(Context context, int itemLayoutId, List<T> mDatas) {
        this.mContext = context;
        this.mInflater = LayoutInflater.from(mContext);
        this.mDatas = mDatas;
        this.mItemLayoutId = itemLayoutId;
    }

    @Override
    public int getCount() {
        return 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) {
        final ViewHolder viewHolder = getViewHolder(position, convertView, parent);
        convert(viewHolder, getItem(position),position);
        return viewHolder.getConvertView();

    }

    public abstract void convert(ViewHolder holder, T item,int postion);

    private ViewHolder getViewHolder(int position, View convertView, ViewGroup parent) {
        return ViewHolder.get(mContext, convertView, parent, mItemLayoutId, position);
    }
}

辅助类viewhodler

public class ViewHolder {

    private final SparseArray<View> mViews;
    private int mPostion;
    private View mConvertView;
    private Context mContext;

    private ViewHolder(Context context, ViewGroup parent, int layoutId, int position) {
        this.mViews = new SparseArray<>();
        this.mPostion = position;
        this.mContext = context;
        mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
        mConvertView.setTag(this);
    }

    /**
     * 拿到一个ViewHolder对象
     *
     * @param context
     * @param convertView
     * @param parent
     * @param layoutId
     * @param position
     * @return
     */
    public static ViewHolder get(Context context, View convertView, ViewGroup parent, int layoutId, int position) {
        if (convertView == null) {
            return new ViewHolder(context, parent, layoutId, position);
        }
        return (ViewHolder) convertView.getTag();
    }

    /**
     * 通过控件的Id获取对于的控件,如果没有则加入views
     *
     * @param viewId
     * @return
     */
    public <T extends View> T getView(int viewId) {

        View view = mViews.get(viewId);
        if (view == null) {
            view = mConvertView.findViewById(viewId);
            mViews.put(viewId, view);
        }
        return (T) view;
    }

    public View getConvertView() {
        return mConvertView;
    }

    /**
     * 设置文本(可以自己添加设置image bitmap color等)
     */
    public ViewHolder setText(int viewId, String text) {
        TextView tv = getView(viewId);
        tv.setText(text);
        return this;
    }
}

2、RecyclerView适配器

CommonRecyclerAdapter

public abstract class CommonRecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerHolder> {

    private Context context;//上下文
    private List<T> list;//数据源
    private LayoutInflater inflater;//布局器
    private int itemLayoutId;//布局id
    private OnItemClickListener listener;//点击事件监听器
    private OnItemLongClickListener longClickListener;//长按监听器
    private RecyclerView recyclerView;

    //在RecyclerView提供数据的时候调用
    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        this.recyclerView = recyclerView;
    }

    @Override
    public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
        super.onDetachedFromRecyclerView(recyclerView);
        this.recyclerView = null;
    }

    /**
     * 定义一个点击事件接口回调
     */
    public interface OnItemClickListener {
        void onItemClick(RecyclerView parent, View view, int position);
    }

    public interface OnItemLongClickListener {
        boolean onItemLongClick(RecyclerView parent, View view, int position);
    }

    public CommonRecyclerAdapter(Context context, int itemLayoutId, List<T> list) {
        this.context = context;
        this.list = list;
        this.itemLayoutId = itemLayoutId;
        inflater = LayoutInflater.from(context);
    }

    @Override
    public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = inflater.inflate(itemLayoutId, parent, false);
        return RecyclerHolder.getRecyclerHolder(context, view);
    }

    @Override
    public void onBindViewHolder(final RecyclerHolder holder, int position) {

        if (listener != null) {
            holder.itemView.setBackgroundResource(R.mipmap.ic_launcher);//设置背景
        }
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (listener != null && view != null && recyclerView != null) {
                    int position = recyclerView.getChildAdapterPosition(view);
                    listener.onItemClick(recyclerView, view, position);
                }
            }
        });
        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                if (longClickListener != null && view != null && recyclerView != null) {
                    int position = recyclerView.getChildAdapterPosition(view);
                    longClickListener.onItemLongClick(recyclerView, view, position);
                    return true;
                }
                return false;
            }
        });
        convert(holder, list.get(position), position);
    }

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

    public void setOnItemClickListener(OnItemClickListener listener) {
        this.listener = listener;
    }

    public void setOnItemLongClickListener(OnItemLongClickListener longClickListener) {
        this.longClickListener = longClickListener;
    }

    /**
     * 填充RecyclerView适配器的方法,子类需要重写
     *
     * @param holder      ViewHolder
     * @param item        子项
     * @param position    位置
     */
    public abstract void convert(RecyclerHolder holder, T item, int position);
}

RecyclerHolder

public class RecyclerHolder extends RecyclerView.ViewHolder {

    private SparseArray<View> views;
    private Context context;

    private RecyclerHolder(Context context, View itemView) {
        super(itemView);
        this.context = context;
        this.views = new SparseArray<>();
    }

    /**
     * 取得一个RecyclerHolder对象
     *
     * @param context  上下文
     * @param itemView 子项
     * @return 返回一个RecyclerHolder对象
     */
    public static RecyclerHolder getRecyclerHolder(Context context, View itemView) {
        return new RecyclerHolder(context, itemView);
    }

    public SparseArray<View> getViews() {
        return this.views;
    }

    /**
     * 通过view的id获取对应的控件,如果没有则加入views中
     *
     * @param viewId 控件的id
     * @return 返回一个控件
     */
    @SuppressWarnings("unchecked")
    public <T extends View> T getView(int viewId) {
        View view = views.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            views.put(viewId, view);
        }
        return (T) view;
    }

    /**
     * 设置字符串
     */
    public RecyclerHolder setText(int viewId, String text) {
        TextView tv = getView(viewId);
        tv.setText(text);
        return this;
    }

    /**
     * 设置图片
     */
    public RecyclerHolder setImageResource(int viewId, int drawableId) {
        ImageView iv = getView(viewId);
        iv.setImageResource(drawableId);
        return this;
    }

    /**
     * 设置图片
     */
    public RecyclerHolder setImageBitmap(int viewId, Bitmap bitmap) {
        ImageView iv = getView(viewId);
        iv.setImageBitmap(bitmap);
        return this;
    }

    /**
     * 设置图片
     */
    public RecyclerHolder setImageByUrl(int viewId, String url) {
        RequestOptions requestOptions = new RequestOptions();
        requestOptions.error(R.mipmap.ic_launcher);
        requestOptions.placeholder(R.mipmap.ic_launcher);
        Glide.with(context).load(url).apply(requestOptions).into((ImageView) getView(viewId));
        return this;
    }
}

3、RecyclerView使用方法,listview的几乎一致

3.1、定义一个数据实体类

public class DataBean {

    /**
     * 标题
     */
    private String title;
    /**
     * 图片地址
     */
    private String url;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public DataBean(String title, String url) {
        this.title = title;
        this.url = url;
    }
}

3.2、定义一个adapter 继承CommonRecyclerAdapter放入数据源实现其抽象方法

public class MyAdapter extends CommonRecyclerAdapter<DataBean> {

    public MyAdapter(Context context, int itemLayoutId, List<DataBean> list) {
        super(context, itemLayoutId, list);
    }

    @Override
    public void convert(RecyclerHolder holder, DataBean item, int position) {

    }
}

其中关联布局可放在Activity中,个人喜欢放在里面

public class MyAdapter extends CommonRecyclerAdapter<DataBean> {

    public MyAdapter(Context context, List<DataBean> list) {
        super(context, R.layout.list_data_item, list);
    }

    @Override
    public void convert(RecyclerHolder holder, DataBean item, int position) {
        //标题
        String title = item.getTitle();
        holder.setText(R.id.item_title, TextUtils.isEmpty(title) ? "-" : title);//三木判断下返回是否为空
        //图片地址
        String url = item.getUrl();
        holder.setImageByUrl(R.id.item_url, url);
    }
}

主布局中Main2Activity

public class Main2Activity extends AppCompatActivity {

    private RecyclerView recycler;
    private List<DataBean> list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        recycler = (RecyclerView) this.findViewById(R.id.recycler);
        if (list == null) {
            list = new ArrayList<>();
        }
        //模拟10条假数据
        for (int i = 0; i < 10; i++) {
            list.add(new DataBean("android", "http://inews.gtimg.com/newsapp_bt/0/876781763/1000"));
        }
        MyAdapter adapter = new MyAdapter(this, list);
        recycler.setLayoutManager(new LinearLayoutManager(this));
        recycler.setAdapter(adapter);
        adapter.setOnItemClickListener(new CommonRecyclerAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(RecyclerView parent, View view, int position) {
                Toast.makeText(Main2Activity.this,"点击事件"+position,Toast.LENGTH_SHORT).show();
            }
        });
        adapter.setOnItemLongClickListener(new CommonRecyclerAdapter.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(RecyclerView parent, View view, int position) {
                Toast.makeText(Main2Activity.this,"长按事件"+position,Toast.LENGTH_SHORT).show();
                return false;
            }
        });
    }
}

activity_main2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/recycler"/>
</LinearLayout>

item布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_height="wrap_content">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/item_title"/>

    <ImageView
        android:layout_marginTop="5dp"
        android:layout_width="wrap_content"
        android:layout_height="100dp"
        android:id="@+id/item_url"/>
</LinearLayout>
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
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;             更多的布局样式 ...         }     } }
通过封装BaseAdapter和RecyclerView.Adapter得到的通用的,简易的Adapter。项目地址:https://github.com/tianzhijiexian/CommonAdapter 效果图:已解决的问题 提升item的独立性,完美支持item被多处复用 item会根据type来做自动复用 支持多种类型的item 一个item仅会调用一次setViews(),避免重复建立监听器 一个item仅会触发一次绑定视图的操作,提示效率 支持dataBinding和其他第三方注入框架 提供了getView()方法来简化findViewById 支持通过item的构造方法来传入Activity对象 支持通过item的构造方法来传入item中事件的回调 提供了getConvertedData(data, type)方法来对item传入的数据做转换,方便拆包和提升item的复用性 支持viewpager的正常加载模式和懒加载 支持快速将listview的适配器切换为recyclerView的适配器 viewpager的notifyDataSetChanged可以正常更新界面 支持recyclerView的添加头部和底部 支持适配器的数据自动绑定,只用操作数据便可,adapter会自动notify界面零、重要接口adapter的item必须实现此接口,接口源码如下:public interface AdapterItem<T> {     /**      * @return item布局文件的layoutId      */     @LayoutRes     int getLayoutResId();     /**      * 初始化views      */     void bindViews(final View root);     /**      * 设置view的参数      */     void setViews();     /**      * 根据数据来设置item的内部views      *      * @param model    数据list内部的model      * @param position 当前adapter调用item的位置      */     void handleData(T model, int position); }例子:public class TextItem implements AdapterItem<DemoModel> {     @Override     public int getLayoutResId() {         return R.layout.demo_item_text;     }     TextView textView;     @Override     public void bindViews(View root) {         textView = (TextView) root.findViewById(R.id.textView);     }     @Override     public void setViews() { }     @Override     public void handleData(DemoModel model, int position) {         textView.setText(model.content);     } }一、ListView GridView的通用适配器——CommonAdapter只需继承CommonAdapter便可实现适配器:listView.setAdapter(new CommonAdapter<DemoModel>(data, 1) {     public AdapterItem<DemoModel> createItem(Object type) {         return new TextItem();     } });二、RecyclerView的通用适配器——CommonRcvAdapter通过继承CommonRcvAdapter来实现适配器:mAdapter = new CommonRcvAdapter<DemoModel>(data) {  public AdapterItem createItem(Object type) {         return new TextItem();   } };三、ViewPager的通用适配器——CommonPagerAdapter通过继承CommonPagerAdapter来实现适配器:viewPager.setAdapter(new CommonPagerAdapter<DemoModel>() {     public AdapterItem createItem(Object type) {         return new TextItem();     } });设计思路1. Adapter如果用adapter常规写法,你会发现代码量很大,可读性低。如果adapter中有多个类型的Item,我们还得在getView()中写很多if-else语句,很乱。 而现在我让adapter的代码量减少到一个8行的内部类,如果你需要更换item只需要动一行代码,真正实现了可插拔化。最关键的是item现在作为了一个独立的对象,可以方便的进行复用。2. AdapterItem和原来方式最为不同的一点就是我把adapter的item作为了一个实体,这种方式借鉴了RecyclerView中ViewHolder的设计。把item作为实体的好处有很多,比如复用啊,封装啊,其余的就不细说了。3. 分层在使用过程中,我发现如果adapter放在view层,那就会影响到view层的独立性。此外adapter中经常有很多数据处理的操作,比如通过type选择item,数据的拆包、转换等操作。于是我还是推荐把adapter放在mvp的p层,或者是mvvm的m层。通过在实际的项目中使用来看,放在m或p层的效果较好,view的复用也比较好做。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值