public abstract class BaseVBAdapter<T, V extends ViewBinding> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
protected List<T> dataList;//数据
protected Context context;//上下文
public BaseVBAdapter(Context context) {
this.context = context;
dataList = new ArrayList<>();
}
/**
* 添加数据
*
* @param dataList 数据
*/
public void setDataList(List<T> dataList) {
if (dataList == null) {
this.dataList = new ArrayList<>();
} else {
this.dataList = dataList;
}
notifyDataSetChanged();
}
/**
* 添加更多的数据
*
* @param dataList 数据
*/
public void addDataList(List<T> dataList) {
if (dataList == null) {
dataList = new ArrayList<>();
}
this.dataList.addAll(dataList);
notifyItemRangeChanged(this.dataList.size() - dataList.size(), this.dataList.size());
}
/**
* 布局绑定
*
* @param parent 父视图
* @param viewType 视图类型
*/
@NotNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
if (viewType == -1) {
View view = new View(context);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
AutoUtils.getPercentHeightSize(needEmptyHeight()));
view.setLayoutParams(lp);
view.setBackgroundResource(needEmptyColor());
return new EmptyHolder(view);
}
V bind = getReflectVB(parent);
if (bind == null) {
return new CustomizeHolder(new View(context));
}
return new CustomizeHolder(bind);
}
/**
* 数据更新
*/
@Override
public void onBindViewHolder(@NonNull @NotNull RecyclerView.ViewHolder viewHolder, int position) {
if (needEmptyView() && viewHolder instanceof EmptyHolder) {
//空视图不需要赋值
return;
}
CustomizeHolder holder = (CustomizeHolder) viewHolder;
T item = dataList.get(position);
V bind = holder.bind;
if (bind == null) {
return;
}
updateData(bind, item, position);
}
/**
* 更新holder数据
*
* @param bind 布局
* @param item 数据
* @param position 位置
*/
protected abstract void updateData(V bind, T item, int position);
/**
* 获取适配器布局bind
*
* @param parent 父布局
* @return 通过反射获取ViewBinding
*/
private V getReflectVB(ViewGroup parent) {
Type type = this.getClass().getGenericSuperclass();
if (type != null) {
Class<V> vbClass = (Class<V>) ((ParameterizedType) type).getActualTypeArguments()[1];
try {
Method method = vbClass.getDeclaredMethod("inflate", LayoutInflater.class, ViewGroup.class, boolean.class);
return (V) method.invoke(null, LayoutInflater.from(context), isNeedParent()?parent:null, false);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
return null;
}
}
return null;
}
protected boolean isNeedParent(){
return true;
}
/**
* 是否需要空占位视图
*
* @return 默认false
*/
protected boolean needEmptyView() {
return false;
}
/**
* 空视图高度
*
* @return 默认200
*/
protected int needEmptyHeight() {
return 200;
}
/**
* 空视图颜色
*
* @return 默认透明
*/
protected int needEmptyColor() {
return android.R.color.transparent;
}
/**
* 获取适配器数组
*
* @return List<T>
*/
public List<T> getDataList() {
return dataList;
}
/**
* 如果需要空视图数组长度加1
*
* @return 数组长度
*/
@Override
public int getItemCount() {
if (needEmptyView()) {
return dataList == null ? 0 : dataList.size() + 1;
}
return dataList == null ? 0 : dataList.size();
}
/**
* 判断是否有空视图
*
* @param position 数据位置
* @return -1代表有空视图
*/
@Override
public int getItemViewType(int position) {
if (position == dataList.size() && needEmptyView()) {
return -1;
}
return super.getItemViewType(position);
}
/**
* 数据holder
*/
public class CustomizeHolder extends RecyclerView.ViewHolder {
private V bind;
CustomizeHolder(V bind) {
super(bind.getRoot());
this.bind = bind;
}
CustomizeHolder(View view) {
super(view);
}
}
/**
* 空视图holder
*/
public static class EmptyHolder extends RecyclerView.ViewHolder {
public EmptyHolder(View view) {
super(view);
}
}
}
(1)实现:
1.通过反射来获取视图的ViewBinding,避免在继承类做重复性操作
2.可添加空占位视图,适用场景,在相对布局总被挡住的底部,可调节底部空视图的高度,颜色和是否需要空占位视图,默认不需要
(2)注意:
1.继承类不要是抽象类,不然会反射获取类型失败
2.采用反射来获取ViewBinding,则混淆文件注意加上-keep class **.databinding.**{*;}
(3)使用:
/**
* @descrilbe 泛型的第一个位置传入数据的类型,第二个位置传入具体的ViewBinding视图
*/
public class TestAdapter extends BaseVBAdapter<TestBean, ItemTestBinding> {
public TestAdapter(Context context) {
super(context);
}
@Override
protected void updateData(ItemTestBinding bind, TestBean item, int position) {
//bind:视图的bind,可直接操作使用
//item:数据
//position:
}
}
1.使用时只需重写构造方法和更新视图数据的方法就可以实现一个简单的适配器,无需重写过多的方法
2.采用Viewbinding可以减少组件的绑定,简化代码结构
3.对于不可避免的需要混淆databinding,那么可以将获取Viewding改为从继承类获取,不使用反射的机制,实现方式为在父类添加一个普通的方法,默认使用反射获取Viewding,代码如下:
protected V getViewBind(ViewGroup parent) {
return getReflectVB(parent);
}
而后在继承类,重写该方法使用具体的bind方式去获取Viewding,代码如下:
@Override
protected ItemTestBinding getViewBind(ViewGroup parent) {
return ItemTestBinding.inflate(LayoutInflater.from(context), parent, false);
}
这样就可以正常的混淆databinding,适配器的使用也是正常的