利用反射整合ViewBinding和ViewHolder

自从DataBinding和ViewBinding出现后,Android开发中获取界面元素就变得非常方便。即使是RecyclerViewViewHolder也可以使用ViewBinding,例如下面这样

public class ItemTestHolder extends RecyclerView.ViewHolder {private final HolderItemTestBinding binding;public static ItemTestHolder newInstance(ViewGroup viewGroup) {HolderItemTestBinding binding = HolderItemTestBinding.inflate(LayoutInflater.from(viewGroup.getContext()), viewGroup, false);return new ItemTestHolder(binding);}public ItemTestHolder(@NonNull HolderItemTestBinding binding) {super(binding.getRoot());this.binding = binding;}public void setData(String text){binding.tvName.setText(text);}
}

或者

public class ItemTestHolder extends RecyclerView.ViewHolder {private final HolderItemTestBinding binding;public ItemTestHolder(@NonNull ViewGroup viewGroup) {super(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.holder_item_test, viewGroup, false));this.binding = HolderItemTestBinding.bind(itemView);}public void setData(String text) {binding.tvName.setText(text);}
}

但是,像这样每次写一遍....inflate(...)的代码也是一件挺麻烦的事情,因此本文就来介绍一种极简的方式来整合ViewBinding和ViewHolder,最终实现像下面这样的代码:

public class ItemTestHolder extends ViewBindingHolder<HolderItemTestBinding> {public ItemTestHolder(@NonNull ViewGroup viewGroup) {super(viewGroup);}public void setData(String text) {getBinding().tvName.setText(text);}
}

ViewBindingHolder基类的实现

import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
import com.yr.corelib.util.ReflectUtils;import java.lang.reflect.*;@Keep
public abstract class ViewBindingHolder<B extends ViewBinding> extends RecyclerView.ViewHolder {private final B binding;public ViewBindingHolder(@NonNull ViewGroup viewGroup) {super(viewGroup);try {Class<? extends ViewBinding> aClass = ReflectUtils.findParameterizedClass(getClass().getGenericSuperclass(), ViewBinding.class);Method inflateMethod = aClass.getMethod("inflate", LayoutInflater.class, ViewGroup.class, boolean.class);try {binding = (B) inflateMethod.invoke(null, LayoutInflater.from(viewGroup.getContext()), viewGroup, false);modifyItemView(binding.getRoot());} catch (IllegalAccessException | InvocationTargetException e) {throw new RuntimeException(e);}} catch (Exception e) {throw new RuntimeException("Something wrong when create Binding:", e);}}public B getBinding() {return binding;}private void modifyItemView(Object newFieldValue) throws Exception {Field field = RecyclerView.ViewHolder.class.getDeclaredField("itemView");if (!field.isAccessible()) {field.setAccessible(true);}field.set(this, newFieldValue);}
}

2. ReflectUtils反射工具

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;public class ReflectUtils {public static <T> Class<? extends T> findParameterizedClass(Class<?> aClass, Class<T> targetClass) {return findParameterizedClass(aClass.getGenericSuperclass(), targetClass);}public static <T> Class<? extends T> findParameterizedClass(Type type, Class<T> targetClass) {if (type instanceof ParameterizedType) {Type[] typeArguments = ((ParameterizedType) type).getActualTypeArguments();for (Type typeArgument : typeArguments) {if (typeArgument instanceof Class) {if (targetClass.isAssignableFrom((Class<?>) typeArgument)) {return (Class<? extends T>) typeArgument;}} else {throw new IllegalStateException("typeArgument is not a Class");}}Type rawType = ((ParameterizedType) type).getRawType();if (rawType.equals(Object.class)) {return null;} else {return findParameterizedClass(rawType, targetClass);}} else if (type instanceof Class) {if (type.equals(Object.class)) {return null;} else {Type superclass = ((Class<?>) type).getGenericSuperclass();return findParameterizedClass(superclass, targetClass);}} else {throw new IllegalStateException("type is not ParameterizedType or Class!");}}
}

3. 用法说明

ViewBindingHolder的使用非常简单,假设你要新建一个名为ImageViewHolder,而布局文件名为holder_image.xml(对应ViewBinding类为HolderImage),那么在配置好ViewBinding后,进行以下步骤:

  1. ImageViewHolder继承ViewBindingHolder
  2. HolderImage作为ViewBindingHolder的泛型参数;
  3. 编写/自动生成一个ViewHolder的默认构造方法;

然后就可以通过getBinding来获取对应的ViewBinding对象了。

当然,也可以不用显式继承,而是匿名内部类的方式来使用ViewBindingHolder,例如:

RecyclerView.Adapter<ViewBindingHolder<HolderItemTestBinding>> adapter = new RecyclerView.Adapter<ViewBindingHolder<HolderItemTestBinding>>() {@NonNull@Overridepublic ViewBindingHolder<HolderItemTestBinding> onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {return new ViewBindingHolder<HolderItemTestBinding>(parent) {};}@Overridepublic void onBindViewHolder(@NonNull ViewBindingHolder<HolderItemTestBinding> holder, int position) {holder.getBinding().tvName.setText("");}@Overridepublic int getItemCount() {return 1;}
};

4. DataBindingHolder的实现

同理,DataBinding也可以采用这种方式封装成一个DataBindingHolder:

import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.databinding.ViewDataBinding;
import androidx.recyclerview.widget.RecyclerView;
import com.yr.corelib.util.ReflectUtils;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;@Keep
public abstract class DataBindingHolder<B extends ViewDataBinding> extends RecyclerView.ViewHolder {private final B binding;public DataBindingHolder(@NonNull ViewGroup viewGroup) {super(viewGroup);try {Class<? extends ViewDataBinding> aClass = ReflectUtils.findParameterizedClass(getClass().getGenericSuperclass(), ViewDataBinding.class);Method inflateMethod = aClass.getMethod("inflate", LayoutInflater.class, ViewGroup.class, boolean.class);try {binding = (B) inflateMethod.invoke(null, LayoutInflater.from(viewGroup.getContext()), viewGroup, false);modifyItemView(binding.getRoot());} catch (IllegalAccessException | InvocationTargetException e) {throw new RuntimeException(e);}} catch (Exception e) {throw new RuntimeException("Something wrong when create Binding:", e);}}public B getBinding() {return binding;}public void bind(int position) {}private void modifyItemView(Object newFieldValue) throws Exception {Field field = RecyclerView.ViewHolder.class.getDeclaredField("itemView");if (!field.isAccessible()) {field.setAccessible(true);}field.set(this, newFieldValue);}
}

利用反射整合ViewBinding和ViewHolder相关推荐

  1. 枚举注解反射整合详解

    一丶枚举 1 ** 2 * 一.枚举类的使用 3 * 1.枚举类的理解:类的对象只有有限个,确定的.我们称此类为枚举类 4 * 2.当需要定义一组常量时,强烈建议使用枚举类 5 * 3.如果枚举类中只 ...

  2. 利用反射实现类的动态加载

    为什么80%的码农都做不了架构师?>>>    //首先定义一个接口来隔离类: public interface Operator { // public java.util.Lis ...

  3. Atitit利用反射获取子类 集合 以及继承树

    Atitit利用反射获取子类 集合 以及继承树 想从父类往下找子类的确是不可能的,要知道只要类不是final的话谁都有继承它的自由不需要事前通知父类. Eclipse实现不是重父类开始找而是重子类往回 ...

  4. 利用反射及ActionFilterAttribute实现MVC权限管理

    1.利用反射获取当前程序集下的所有控制器和方法,拼接后写入到数据库. public void GetRightInfo(){var ControllerIDMax = db.rights_info.S ...

  5. android利用反射调用截屏api,Android利用反射机制调用截屏方法和获取屏幕宽高的方法...

    想要在应用中进行截屏,可以直接调用 View 的 getDrawingCache 方法,但是这个方法截图的话是没有状态栏的,想要整屏截图就要自己来实现了. 还有一个方法可以调用系统隐藏的 screen ...

  6. CN.Text开发笔记—利用反射将数据读入实体类

    在实际开发中,我们经常需要从数据库中读取数据并赋值给实体类的相应属性.在.Text的DataDTOProvider中存在大量这样的代码, 比如: public Role[] GetRoles(int  ...

  7. 利用反射机制获取未知类型的枚举的信息

    原文:利用反射机制获取未知类型的枚举的信息 开发游戏设置选项遇到一个问题,我有两个枚举,一个是屏幕分辨率,一个是语言 我需要在不知道一个枚举到底是哪一个枚举类型的情况下,获取这个枚举的值以及这个枚举类 ...

  8. java设计模——反射的应用 (利用反射来去除if判断语句)

    利用反射来去除if判断语句 我的以前写的一个查分系统,就是部长让我写的那个,使用一个分发器(函数),他会根据传递进来的字符串参数调用不同的方. If("add".equalsIgn ...

  9. 使用基于注解的mybatis时,利用反射和注解生成sql语句

    在开发时遇到一个问题,在使用基于注解的mybatis插入一个对象到mysql时,在写sql语句时需要列出对象的所有属性,所以在插入一个拥有10个以上属性的对象时sql语句就会变得很长,写起来也很不方便 ...

最新文章

  1. android cmd 右键菜单不见了,为Windows右键菜单提供打开命令行选项
  2. python No tests were found问题解决方法
  3. Intel 64/x86_64/x86/IA-32处理器标志寄存器详解(6) - 64位RFLAGS
  4. 你听过或见过最无耻的一句话是什么?
  5. My first project
  6. 4.MySQL优化---多表查询优化
  7. SQL查询效率-100w数据查询只要1秒
  8. springboot实现第三方qq登入
  9. UVA 473-Raucous Rockers(DP)
  10. 分析 2017年淘宝天猫活动时间安排
  11. 傅里叶描述子、HOG特征描述子原理及matlab代码
  12. 单片机c语言led灯闪烁程序,单片机LED灯闪烁程序
  13. JAVA I/O之神奇的RandomAccessFile(快速定位文件任意位置,修改或插入)
  14. arcgis数据的M/Z值设置问题
  15. mac使用u盘安装系统
  16. 陳三甲网络笔记:几条赚钱感悟!
  17. Jetson AGX xavier测试六叶树Usb转Can卡通信记录笔记
  18. 逆时针螺旋矩阵的学习
  19. 《黑客攻防技术宝典:Web实战篇》习题答案(三)
  20. .net程序员工作两年总结

热门文章

  1. python --pyautogui(模拟鼠标键盘操作)
  2. 工业自动化MODBUS协议读写器读卡器配置软件|工具之读写卡模式配置操作攻略
  3. 数据结构之通用树结构的实现
  4. 浅谈Alpha Go所涉及的深度学习技术
  5. python生成高斯(gauss)数据并保存为txt文件
  6. 腾讯微博开放平台 android登录界面显示为pc登录界面 解决方案
  7. Java使用mysql_connector驱动包连接数据库
  8. U300 超高频读写器 - 固定式rfid读写器
  9. 网上购物管理系统的设计与实现
  10. SAP TMS传输系统配置手册