封装Android RecyclerAdapter

本文详细探讨了Android中的RecyclerAdapter的原理和使用,包括如何进行数据绑定、视图复用以及性能优化。通过实例代码展示了如何封装一个自定义的RecyclerAdapter,以提升UI列表的性能和易用性。

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


一·创建RecyclerAdapter的java文件

import android.annotation.SuppressLint;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.zyf.italker.common.R;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import butterknife.ButterKnife;//需引入Butterknife,自行百度,如不想则将@Bind全部替换为普通findViewById
import butterknife.Unbinder;


public abstract class RecyclerAdapter<Data> extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder<Data>>
        implements View.OnClickListener, View.OnLongClickListener, AdapterCallback<Data> {
    private final List<Data> mDataList;
    private AdapterListener<Data> mListener;

    /**
     * 构造函数模块
     * */
    public RecyclerAdapter() {
        this(null);
    }
    public RecyclerAdapter(AdapterListener<Data> listener) {
        this(new ArrayList<Data>(), listener);
    }
    public RecyclerAdapter(List<Data> dataList, AdapterListener<Data> listener) {
        this.mDataList = dataList;
        this.mListener = listener;
    }


    /*
     * 复写默认的布局类型返回
     * @param position 坐标
     * @return 类型,其实复写后返回的都是XML文件的ID
     * */

    @Override
    public int getItemViewType(int position) {
        return getItemViewType(position, mDataList.get(position));
    }

    /**
     * 得到布局的类型
     * @param position 坐标
     * @param data 当前的数据
     * @return XML文件的ID,用于创建ViewHolder
     */
    @LayoutRes
    protected abstract int getItemViewType(int position, Data data);

    /**
    *创建一个ViewHolder
     * @param parent RecyclerView
     * @param viewType 界面的类型,约定为XML布局的id
     * @return ViewHolder
     * */
    @SuppressLint("InvalidRUsage")
    @NonNull
    @Override
    public ViewHolder<Data> onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //得到LayoutInflater用于把XML初始化为View
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        //把XML id为viewType的文件初始化为一个 root View
        View root = inflater.inflate(viewType, parent, false);
        //通过子类必须实现的方法,得到一个ViewHolder
        ViewHolder<Data> holder = onCreatViewHolder(root, viewType);
        //设置事件点击
        root.setOnClickListener(this);
        root.setOnLongClickListener(this);
        //设置View的Tag为ViewHolder,进行双向绑定
        root.setTag(R.id.tag_recycler_holder, holder);
        //进行界面注解的绑定
        holder.unbinder = ButterKnife.bind(holder, root);
        //绑定callback
        holder.callback = this;
        return holder;
    }


    /**
    得到一个新的ViewHolder
     *@param root 根布局
     *@param viewType 布局类型,其实就是XML的ID
     *@return ViewHolder

     * */
    protected abstract ViewHolder<Data> onCreatViewHolder(View root, int viewType);


    /**
     * 绑定数据到一个Holder上
     * @param holder ViewHolder
     * @param position 坐标
     */
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        //得到需要绑定的数据
        Data data = mDataList.get(position);
        //出发Holder的绑定方法
        holder.bind(data);

    }


    /**
     * 得到当前集合的数据量
     **/
    @Override
    public int getItemCount() {
        return mDataList.size();
    }

    /**
     * 返回整个集合
     *
     * @return List<Data>
     */
    public List<Data> getItems() {
        return mDataList;
    }




    /*插入一条数据并通知插入*/
    public void add(Data data) {
        mDataList.add(data);
        notifyItemInserted(mDataList.size() - 1);
    }

    /*插入一堆数据并通知这段集合更新*/
    public void add(Data... dataList) {
        if (dataList != null && dataList.length > 0) {
            int startPos = mDataList.size();
            Collections.addAll(mDataList, dataList);
            notifyItemRangeInserted(startPos, dataList.length);
        }
    }

    /*插入一堆数据并通知这段集合更新*/
    public void add(Collection<Data> dataList) {
        if (dataList != null && dataList.size() > 0) {
            int startPos = mDataList.size();
            mDataList.addAll(dataList);
            notifyItemRangeInserted(startPos, dataList.size());
        }
    }

    /*
     * 删除操作
     * */
    public void clear() {
        mDataList.clear();
        notifyDataSetChanged();
    }

    /*
     * 替换为一个新的集合,其中包括了清空
     * @param dataList 一个新的集合
     * */
    public void replace(Collection<Data> dataList) {
        mDataList.clear();
        if (dataList == null || dataList.size() == 0)
            return;
        mDataList.addAll(dataList);
        notifyDataSetChanged();
    }

    @Override
    public void update(Data data, ViewHolder<Data> holder) {
        //得到当前ViewHolder的坐标
        int pos = holder.getAdapterPosition();
        if(pos>=0){
            //进行数据的移除与更新
            mDataList.remove(pos);
            mDataList.add(pos,data);
            //通知这个坐标下的数据有更新
            notifyItemChanged(pos);
        }
    }

    @Override
    public void onClick(View view) {
        @SuppressLint("InvalidRUsage")
        ViewHolder viewHolder = (ViewHolder) view.getTag(R.id.tag_recycler_holder);
        if (this.mListener != null) {
            //得到ViewHolder当前对应的适配器坐标
            int pos = viewHolder.getAdapterPosition();
            //回调方法
            this.mListener.onItemClick(viewHolder, mDataList.get(pos));
        }

    }

    @Override
    public boolean onLongClick(View view) {
        @SuppressLint("InvalidRUsage")
        ViewHolder viewHolder = (ViewHolder) view.getTag(R.id.tag_recycler_holder);
        if (this.mListener != null) {
            //得到ViewHolder当前对应的适配器坐标
            int pos = viewHolder.getAdapterPosition();
            //回调方法
            this.mListener.onItemLongClick(viewHolder, mDataList.get(pos));
            return true;
        }
        return false;
    }

    /*
     * 设置适配器监听
     * */
    public void setListener(AdapterListener<Data> adapterListener) {
        this.mListener = adapterListener;
    }

    /*
     * 我们的自定义监听器
     * @param <Data>泛型
     * */
    public interface AdapterListener<Data> {
        //当Cell点击的时候触发
        void onItemClick(RecyclerAdapter.ViewHolder holder, Data data);

        //当Cell长按的时候触发
        void onItemLongClick(RecyclerAdapter.ViewHolder holder, Data data);
    }

    /*
     * 自定义的ViewHolder
     * @param<Data>泛型类型
     * */
    public static abstract class ViewHolder<Data> extends RecyclerView.ViewHolder {
        private Unbinder unbinder;
        private AdapterCallback callback;
        protected Data mData;

        public ViewHolder(View itemView) {
            super(itemView);
        }

        /**
         * 用于绑定数据的触发
         *
         * @param data 绑定的数据
         */
        void bind(Data data) {
            this.mData = data;
            onBind(data);
        }

        /*
        * 当触发绑定数据时的回调,必须复写。
        * @param data 绑定的数据
        *
        */
        protected abstract void onBind(Data data);

        /*
        Holder自己对自己对应的data进行更新操作
        */
        public void updateData(Data data) {
            if (this.callback != null) {
                this.callback.update(data, this);
            }
        }

    }

    /**
    *对回掉接口做一次实现
     * @param <Data>
    */
    public static abstract class AdapterListenerImpl<Data> implements AdapterListener<Data>{

        @Override
        public void onItemClick(ViewHolder holder, Data data) {

        }

        @Override
        public void onItemLongClick(ViewHolder holder, Data data) {

        }
    }

}

二·同目录下创建java文件AdapterCallback
public interface AdapterCallback<Data> {
    void update(Data data, RecyclerAdapter.ViewHolder<Data>holder);

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值