万能适配器
/**
* 万能适配器
* item点击事件、三级缓存、数据更新、动画
* @param <T> 实体类
* @param <K> 继承BaseViewHolder的ViewHolder
*/
public abstract class BaseRecyclerViewAdapter<T,K extends BaseViewHolder> extends RecyclerView.Adapter<K>{
private int resource;
public List<T> data;
private Context context;
//是否是多布局
private boolean isMultiItem = false;
/**
* 单布局构造函数
* @param resource 布局文件
* @param data item数据
*/
public BaseRecyclerViewAdapter(@LayoutRes int resource, @Nullable List<T> data){
this.data = data == null ? new ArrayList<T>() : data;
if (resource != 0) {
this.resource = resource;
isMultiItem = false;
}
}
/**
* 多布局的类型
*/
private SparseIntArray layouts;
private int getLayoutId(@LayoutRes int viewType) {
return layouts.get(viewType);
}
/**
* 添加新布局
* @param viewType 新布局
*/
public void setLayouts(@LayoutRes int viewType){
layouts.put(viewType,viewType);
}
/**
* 多布局构造函数
* @param data item数据
*/
protected BaseRecyclerViewAdapter(@Nullable List<T> data) {
this(0, data);
isMultiItem = true;
layouts = new SparseIntArray();
List<BaseMultiItemEntity> baseMultiItemEntities = (List<BaseMultiItemEntity>) data;
if (baseMultiItemEntities != null) {
for (BaseMultiItemEntity t :baseMultiItemEntities){
layouts.put(t.getItemType(), t.getItemType());
}
}
}
public Context getContext(){
return context;
}
/**
* item 点击事件
*/
private OnItemClickListener onItemClickListener;
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public final OnItemClickListener getOnItemClickListener() {
return onItemClickListener;
}
/**
* item 长按事件
*/
private OnItemLongClickListener onItemLongClickListener;
public interface OnItemLongClickListener {
void onItemLongClick(View view, int position);
}
public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener) {
this.onItemLongClickListener = onItemLongClickListener;
}
/**
* item中子view的点击事件
* 必须先在adapter的convert方法里面通过viewHolder.addOnClickListener绑定一下的控件id
*/
private OnItemChildClickListener mOnItemChildClickListener;
public interface OnItemChildClickListener {
void onItemChildClick(BaseRecyclerViewAdapter adapter, View view, int position);
}
public void setOnItemChildClickListener(OnItemChildClickListener listener) {
mOnItemChildClickListener = listener;
}
@Nullable
public final OnItemChildClickListener getOnItemChildClickListener() {
return mOnItemChildClickListener;
}
/**
* item中子view的长按事件
* 必须先在adapter的convert方法里面通过viewHolder.addOnLongClickListener绑定一下的控件id
*/
private OnItemChildLongClickListener mOnItemChildLongClickListener;
public interface OnItemChildLongClickListener {
/**
* 长按事件
* @return 如果回调消耗了长按,则返回true,否则返回false
*/
boolean onItemChildLongClick(BaseRecyclerViewAdapter adapter, View view, int position);
}
public void setOnItemChildLongClickListener(OnItemChildLongClickListener listener) {
mOnItemChildLongClickListener = listener;
}
@Nullable
public final OnItemChildLongClickListener getOnItemChildLongClickListener() {
return mOnItemChildLongClickListener;
}
@NonNull
@Override
public K onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
context = viewGroup.getContext();
Application application = (Application) context.getApplicationContext();
View view;
LayoutInflater mLayoutInflater = LayoutInflater.from(context);
if (isMultiItem){
view = mLayoutInflater.inflate(getLayoutId(viewType), viewGroup, false);
}else {
view = mLayoutInflater.inflate(resource, viewGroup, false);
}
K baseViewHolder = createBaseViewHolder(view);
bindViewClickListener(baseViewHolder);
baseViewHolder.setAdapter(this, application);
return baseViewHolder;
}
/**
* 如果要在适配器中使用BaseViewHolder的子类,
* 必须覆盖该方法以创建新的ViewHolder。
* @param view
* @return
*/
protected K createBaseViewHolder(View view) {
Class temp = getClass();
Class z = null;
while (z == null && null != temp) {
z = getInstancedGenericKClass(temp);
temp = temp.getSuperclass();
}
K k;
// 泛型擦除会导致z为null
if (z == null) {
k = (K) new BaseViewHolder(view);
} else {
k = createGenericKInstance(z, view);
}
return k != null ? k : (K) new BaseViewHolder(view);
}
/**
* 得到通用参数.
* @param z
* @return
*/
private Class getInstancedGenericKClass(Class z) {
Type type = z.getGenericSuperclass();
if (type instanceof ParameterizedType) {
Type[] types = ((ParameterizedType) type).getActualTypeArguments();
for (Type temp : types) {
if (temp instanceof Class) {
Class tempClass = (Class) temp;
if (BaseViewHolder.class.isAssignableFrom(tempClass)) {
return tempClass;
}
} else if (temp instanceof ParameterizedType) {
Type rawType = ((ParameterizedType) temp).getRawType();
if (rawType instanceof Class && BaseViewHolder.class.isAssignableFrom((Class<?>) rawType)) {
return (Class<?>) rawType;
}
}
}
}
return null;
}
/**
* 创建新的ViewHolder
* @param z
* @param view
* @return
*/
private K createGenericKInstance(Class z, View view) {
try {
Constructor constructor;
// inner and unstatic class
if (z.isMemberClass() && !Modifier.isStatic(z.getModifiers())) {
constructor = z.getDeclaredConstructor(getClass(), View.class);
constructor.setAccessible(true);
return (K) constructor.newInstance(this, view);
} else {
constructor = z.getDeclaredConstructor(View.class);
constructor.setAccessible(true);
return (K) constructor.newInstance(view);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
/**
* item的点击事件/长按事件
* @param baseViewHolder
*/
private void bindViewClickListener(final BaseViewHolder baseViewHolder) {
if (baseViewHolder == null) {
return;
}
final View view = baseViewHolder.itemView;
//事件
if (onItemClickListener != null) {
view.setOnClickListener(v -> {
onItemClickListener.onItemClick(view, baseViewHolder.getLayoutPosition());
});
}
if (onItemLongClickListener != null){
view.setOnLongClickListener(v -> {
onItemLongClickListener.onItemLongClick(view, baseViewHolder.getLayoutPosition());
return false;
});
}
}
@Override
public void onBindViewHolder(@NotNull K holder, int position) {
T item = null;
if (position >= 0 && position < data.size()){
item = data.get(position);
}
convert(holder,item ,position);
}
public abstract void convert(@NonNull K holder, T item, int position);
@Override
public int getItemCount() {
return data.size();
}
/**
* 是否是新布局
* @param element BaseMultiItemEntity
*/
public void isNewLayout(@NonNull T element){
if (isMultiItem){
int itemType = ((BaseMultiItemEntity) element).getItemType();
if (getLayoutId(itemType) == 0 ){
layouts.put(itemType,itemType);
}
}
}
/**
* 是否是新布局
* @param newData BaseMultiItemEntity集合
*/
private void isNewLayout(@NonNull Collection<? extends T> newData){
if (isMultiItem){
for (T element :newData){
int itemType = ((BaseMultiItemEntity) element).getItemType();
if (getLayoutId(itemType) == 0 ){
layouts.put(itemType,itemType);
}
}
}
}
/**
* 在列表最后添加一个item
* @param element item的数据
*/
public void addNewItem(@NonNull T element) {
isNewLayout(element);
data.add(element);
notifyItemInserted(data.size());
compatibilityDataSizeChanged(1);
}
/**
* 在指定位置添加一个item,如果position越界则添加到列表最后
* @param position item添加的位置
* @param element item的数据
*/
public void addNewItem(@IntRange(from = 0) int position,@NonNull T element) {
if (position < data.size()){
isNewLayout(element);
data.add(position, element);
//更新数据集用notifyItemInserted(position)与notifyItemRemoved(position) 否则没有动画效果。
//首个Item位置做增加操作
notifyItemInserted(position);
compatibil