BaseRecyclerViewAdapterHelper源码解读(一) 封装简单的adapter和万能的BaseViewHolder

BaseRecyclerViewAdapterHelper源码解读(一)

1. 封装万能的BaseViewHolder

这是所有ViewHolder的父类

  • 通过SparseArray存储item布局中的控件
  • 通过getView()去获取控件,如果在SparseArray中存在则直接获取,如果不存在则findViewById()然后再插入SparseArray中
  • 设置一些常用操作:设置文本,点击事件,颜色….

SparseArray比HashMap更省内存,在某些条件下性能更好,主要是因为它避免了对key的自动装箱(int转为Integer类型),它内部则是通过两个数组来进行数据存储的,一个存储key,另外一个存储value,为了优化性能,它内部对数据还采取了压缩的方式来表示稀疏数组的数据,从而节约内存空间.


import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorLong;
import android.support.annotation.DrawableRes;
import android.support.annotation.FloatRange;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.support.v7.widget.RecyclerView;
import android.text.SpannableStringBuilder;
import android.util.SparseArray;
import android.view.View;
import android.widget.Checkable;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * author xingyun
 * create at 2017/9/26 16:54
 * description:适用所有RecyclerView的ViewHolder
 */
public class BaseViewHolder extends RecyclerView.ViewHolder {

    //子布局中的控件
    private SparseArray<View> mItemViews;
    //子布局
    private View mView;

    //初始化ViewHolder
    public BaseViewHolder(View itemView) {
        super(itemView);
        mView = itemView;
        mItemViews = new SparseArray<>();
    }

    /**
     * 获取子控件
     * <p>
     * 子控件的id
     *
     * @param viewId 返回子控件
     * @return
     */
    public View getView(@IdRes int viewId) {
        View view = mItemViews.get(viewId);
        if (view == null) {
            view = mView.findViewById(viewId);
            mItemViews.put(viewId, view);
        }
        return view;
    }

    /**
     * 通过strings.xml文件给TextView设置文本
     * <p>
     * 子控件的id
     *
     * @param viewId 子控件在strings.xml中的文本
     * @param resId  返回子控件
     * @return BaseViewHolder
     */
    public BaseViewHolder setText(@IdRes int viewId, @StringRes int resId) {
        TextView textView = (TextView) getView(viewId);
        textView.setText(resId);
        return this;
    }

    /**
     * 通过String给TextView设置文本
     * <p>
     * 子控件的id
     *
     * @param viewId 子控件中的文本
     * @param text   返回子控件
     * @return BaseViewHolder
     */
    public BaseViewHolder setText(@IdRes int viewId, String text) {
        TextView textView = (TextView) getView(viewId);
        if (text != null) {
            textView.setText(text);
        } else {
            textView.setText("");
        }
        return this;
    }

    /**
     * 通过SpannableStringBuilder给TextView设置文本
     *
     * @param viewId View的id
     * @param text   文本
     * @return BaseViewHolder
     */
    public BaseViewHolder setText(@IdRes int viewId, SpannableStringBuilder text) {
        TextView textView = (TextView) getView(viewId);
        if (text != null) {
            textView.setText(text);
        } else {
            textView.setText("");
        }
        return this;
    }

    /**
     * 通过drawable文件夹中的资源设置图片
     *
     * @param viewId view的id
     * @param resId  文本
     * @return BaseViewHolder
     */
    public BaseViewHolder setImageResource(@IdRes int viewId, @DrawableRes int resId) {
        ImageView imageView = (ImageView) getView(viewId);
        imageView.setImageResource(resId);
        return this;
    }

    /**
     * 通过Bitmap设置图片
     *
     * @param viewId view Id
     * @param bitmap Bitmap
     * @return BaseViewHolder
     */
    public BaseViewHolder setImageBitmap(@IdRes int viewId, @NonNull Bitmap bitmap) {
        ImageView imageView = (ImageView) getView(viewId);
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap);
        }
        return this;
    }

    /**
     * 通过Drawable设置图片
     *
     * @param viewId View的id
     * @param drawable Drawable
     * @return BaseViewHolder
     */
    public BaseViewHolder setImageDrawable(@IdRes int viewId, @NonNull Drawable drawable) {
        ImageView imageView = (ImageView) getView(viewId);
        if (drawable != null) {
            imageView.setImageDrawable(drawable);
        }
        return this;
    }

    /**
     * 通过一串数字设置背景色
     *
     * @param viewId View的id
     * @param color 颜色值 16进制
     * @return BaseViewHolder
     */
    public BaseViewHolder setBackgroundColor(@IdRes int viewId, @ColorLong int color) {
        View view = getView(viewId);
        view.setBackgroundColor(color);
        return this;
    }

    /**
     * 通过drawable文件夹设置背景图
     *
     * @param viewId View的id
     * @param backgroundRes Resource
     * @return BaseViewHolder
     */
    public BaseViewHolder setBackgroundResource(@IdRes int viewId, @DrawableRes int backgroundRes) {
        View view = getView(viewId);
        view.setBackgroundResource(backgroundRes);
        return this;
    }


    /**
     * 通过Drawable设置背景图
     *
     * @param viewId View的id
     * @param drawable Drawable
     * @return BaseViewHolder
     */
    public BaseViewHolder setBackgroundDrawable(@IdRes int viewId, Drawable drawable) {
        View view = getView(viewId);
        if (drawable != null) {
            view.setBackground(drawable);
        }
        return this;
    }

    /**
     * 通过一串数字设置文字颜色
     *
     * @param viewId View的id
     * @param textColor 颜色值 16进制
     * @return BaseViewHolder
     */
    public BaseViewHolder setTextColor(@IdRes int viewId, @ColorLong int textColor) {
        TextView textView = (TextView) getView(viewId);
        textView.setTextColor(textColor);
        return this;
    }

    /**
     * 通过float设置透明度
     *
     * @param viewId View的id
     * @param value 透明度  范围:[0.0,1.0]
     * @return BaseViewHolder
     */
    public BaseViewHolder setAlpha(@IdRes int viewId, @FloatRange(from = 0.0, to = 1.0) float
            value) {
        getView(viewId).setAlpha(value);
        return this;
    }

    /**
     * 通过boolean类型设置是否显示
     *
     * @param viewId View的id
     * @param visible 是否可见 true:可见;  false:不可见,Gone
     * @return BaseViewHolder
     */
    public BaseViewHolder setVisible(@IdRes int viewId, boolean visible) {
        View view = getView(viewId);
        view.setVisibility(visible ? view.VISIBLE : View.GONE);
        return this;
    }

    /**
     * 缓存子控件上界面的数据
     *
     * @param viewId View的id
     * @param tag 需要缓存的数据
     * @return BaseViewHolder
     */
    public BaseViewHolder setTag(@IdRes int viewId, Object tag) {
        View view = getView(viewId);
        view.setTag(tag);
        return this;
    }

    /**
     * 设置某一位置子控件的数据
     *
     * @param viewId View的id
     * @param key 数据标识
     * @param tag 数据
     * @return BaseViewHolder
     */
    public BaseViewHolder setTag(@IdRes int viewId, int key, Object tag) {
        View view = getView(viewId);
        view.setTag(key, tag);
        return this;
    }

    /**
     * 设置子控件是否选中
     *
     * @param viewId  View的id
     * @param checked true:选中   false:未选中
     * @return BaseViewHolder
     */
    public BaseViewHolder setChecked(@IdRes int viewId, boolean checked) {
        Checkable checkable = (Checkable) getView(viewId);
        checkable.setChecked(checked);
        return this;
    }

    /**
     * 设置子控件的点击事件
     *
     * @param viewId View的id
     * @param listener OnClickListener监听器
     * @return BaseViewHolder
     */
    public BaseViewHolder setOnClickListener(@IdRes int viewId, @NonNull View.OnClickListener
            listener) {
        View view = getView(viewId);
        if (listener != null) {
            view.setOnClickListener(listener);
        }
        return this;
    }

    /**
     * 设置子控件的触摸事件
     *
     * @param viewId View的id
     * @param listener OnTouchListener
     * @return BaseViewHolder
     */
    public BaseViewHolder setOnTouchListener(@IdRes int viewId, @NonNull View.OnTouchListener
            listener) {
        View view = getView(viewId);
        if (listener != null) {
            view.setOnTouchListener(listener);
        }
        return this;
    }

    /**
     * 设置子控件的长按事件
     *
     * @param viewId View的id
     * @param listener OnLongClickListener
     * @return BaseViewHolder
     */
    public BaseViewHolder setOnLongClickListener(@IdRes int viewId, @NonNull View
            .OnLongClickListener
        listener) {
        View view = getView(viewId);
        if (listener != null) {
            view.setOnLongClickListener(listener);
        }
        return this;
    }
}

2. 封装简单的Adapter

  • 将重复的方法那些全部抽取到父类(Abstract)免得每次都重复写
  • 父类的泛型是 Bean对象,BaseViewHolder
  • 在onCreateViewHolder()里面写点击事件比较好,因为在onBindViewHolder()里面写的话,每次都要去绑定,会产生多余的消耗.
  • 然后onBindViewHolder()方法是需要每个子类去实现的,我们可以提供一个convert()方法在里面,暴露给外面实现,用于绑定数据.
  • 添加item,移除item->封装
  • 然后封装item点击事件,item长按事件
package com.xfhy.basequickadapter;

import android.content.Context;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.List;

/**
 * author feiyang
 * create at 2017/10/16 15:45
 * description:
 */
public abstract class BaseQuickAdapter<T, K extends BaseViewHolder> extends RecyclerView
        .Adapter<K> {

    private Context mContext;
    /**
     * 数据集合
     */
    private List<T> dataList;
    /**
     * RecyclerView中普通item的布局id
     */
    private int layoutResId;
    /**
     * 子项item点击事件
     */
    private OnItemClickListener onItemClickListener;
    /**
     * 子项item长按事件
     */
    private OnItemLongClickListener onItemLongClickListener;

    public BaseQuickAdapter(Context context) {
        this.mContext = context;
    }

    /**
     * 此构造方法必须调用
     *
     * @param context     Context
     * @param layoutResId 子项普通item布局
     * @param dataList    子项数据集合
     */
    public BaseQuickAdapter(Context context, int layoutResId, List<T> dataList) {
        this.mContext = context;
        this.layoutResId = layoutResId;
        this.dataList = dataList;
    }

    @Override
    public K onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(layoutResId, parent, false);
        final BaseViewHolder baseViewHolder = new BaseViewHolder(view);

        // item点击事件
        if (onItemClickListener != null) {
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onItemClickListener.onItemClick(v, baseViewHolder.getLayoutPosition());
                }
            });
        }

        // item长按事件
        if (onItemLongClickListener != null) {
            view.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    return onItemLongClickListener.onLongClick(v, baseViewHolder
                            .getLayoutPosition());
                }
            });
        }
        return (K) baseViewHolder;
    }

    @Override
    public void onBindViewHolder(K holder, int position) {
        convert(holder, dataList.get(position));
    }

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

    /**
     * 绑定数据
     *
     * @param holder BaseViewHolder
     * @param item   item数据
     */
    protected abstract void convert(BaseViewHolder holder, T item);

    /**
     * 设置item点击事件
     *
     * @param onItemClickListener OnItemClickListener
     */
    public void setOnItemClickListener(@NonNull OnItemClickListener
                                               onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    /**
     * 设置item长按事件
     *
     * @param onItemLongClickListener OnItemLongClickListener
     */
    public void setOnItemLongClickListener(@NonNull OnItemLongClickListener
                                                   onItemLongClickListener) {
        this.onItemLongClickListener = onItemLongClickListener;
    }

    /**
     * item点击监听器
     */
    public interface OnItemClickListener {
        /**
         * item点击事件回调
         *
         * @param view     触发事件View
         * @param position 触发事件的view所在RecyclerView中的位置
         */
        void onItemClick(View view, int position);
    }

    /**
     * item长按监听器
     */
    public interface OnItemLongClickListener {
        /**
         * item长按事件回调
         *
         * @param view     触发事件View
         * @param position 触发事件的view所在RecyclerView中的位置
         * @return 是否消费
         */
        boolean onLongClick(View view, int position);
    }

    /**
     * 删除item
     *
     * @param position 删除item的位置
     */
    public void removeItem(@IntRange(from = 0) int position) {
        if (dataList == null) {
            return;
        }
        if (position >= dataList.size()) {
            return;
        }

        dataList.remove(position);
        notifyItemRemoved(position);
    }

    /**
     * 新增item
     *
     * @param position 新增item位置
     * @param item     item数据
     */
    public void addItem(@IntRange(from = 0) int position, @NonNull T item) {
        if (dataList == null) {
            return;
        }
        if (position > dataList.size()) {
            return;
        }
        dataList.add(position, item);
        notifyItemInserted(position);
    }

}
Android BaseViewHolder 是一个通用的 ViewHolder 类,它可以用于 RecyclerView 中的多个 Adapter 中。它的作用是将 RecyclerView 中的 itemView 与数据绑定起来,以便于显示数据。通常它包含了一些常用的方法,例如 findViewById() 等,以便于在 itemView 中查找和设置控件。 以下是一个简单BaseViewHolder 示例代码: ``` public abstract class BaseViewHolder<T> extends RecyclerView.ViewHolder { public BaseViewHolder(View itemView) { super(itemView); } public abstract void bind(T data); protected <T extends View> T findViewById(@IdRes int id) { return itemView.findViewById(id); } } ``` 在这个示例中,BaseViewHolder 是一个抽象类,它包含了一个 bind() 方法用于绑定数据,一个 findViewById() 方法用于在 itemView 中查找控件。我们可以通过继承 BaseViewHolder 来创建一个自定义的 ViewHolder 类,例如: ``` public class MyViewHolder extends BaseViewHolder<String> { private TextView textView; public MyViewHolder(View itemView) { super(itemView); textView = findViewById(R.id.text_view); } @Override public void bind(String data) { textView.setText(data); } } ``` 在这个示例中,我们创建了一个 MyViewHolder 类,它继承自 BaseViewHolder<String>,并且实现了 bind() 方法和构造方法。在构造方法中,我们通过 findViewById() 方法来查找 itemView 中的 TextView 控件,并将它保存到 textView 变量中。在 bind() 方法中,我们将数据设置到 textView 中,以便于显示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值