当前位置:网站首页>利用反射整合ViewBinding和ViewHolder
利用反射整合ViewBinding和ViewHolder
2022-06-30 03:28:00 【乐征skyline】
利用反射整合ViewBinding和ViewHolder
自从DataBinding和ViewBinding出现后,Android开发中获取界面元素就变得非常方便。即使是RecyclerView的ViewHolder也可以使用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后,进行以下步骤:
- 让
ImageViewHolder继承ViewBindingHolder; - 将
HolderImage作为ViewBindingHolder的泛型参数; - 编写/自动生成一个
ViewHolder的默认构造方法;
然后就可以通过getBinding来获取对应的ViewBinding对象了。
当然,也可以不用显式继承,而是匿名内部类的方式来使用ViewBindingHolder,例如:
RecyclerView.Adapter<ViewBindingHolder<HolderItemTestBinding>> adapter = new RecyclerView.Adapter<ViewBindingHolder<HolderItemTestBinding>>() {
@NonNull
@Override
public ViewBindingHolder<HolderItemTestBinding> onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewBindingHolder<HolderItemTestBinding>(parent) {
};
}
@Override
public void onBindViewHolder(@NonNull ViewBindingHolder<HolderItemTestBinding> holder, int position) {
holder.getBinding().tvName.setText("");
}
@Override
public 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);
}
}
边栏推荐
- laravel9本地安裝
- 4-4 beauty ranking (10 points)
- Auto.js学习笔记16:按项目保存到手机上,不用每次都保存单个js文件,方便调试和打包
- Global and Chinese market of bronze valves 2022-2028: Research Report on technology, participants, trends, market size and share
- MySQL + JSON = King fried
- Feign 坑
- QT中foreach的使用
- Mysql性能优化(6):读写分离
- [0x0] open questions left by the principal
- Dripping backward (II)
猜你喜欢

1148_ Makefile learning_ Targets, variables, and wildcards in makefile

51 single chip microcomputer indoor environment monitoring system, mq-2 smoke sensor and DHT11 temperature and humidity sensor, schematic diagram, C programming and simulation

Arrangement of language resources of upgraded version

Use of custom MVC

C#【高级篇】 C# 多线程

Redis is used in Windows system

Auto. JS learning notes 16: save to the mobile phone by project, instead of saving a single JS file every time, which is convenient for debugging and packaging

Principle, advantages and disadvantages of three operating modes of dc/dc converter under light load

Redis中的SDS理解

产品思维 | 无人机快递的未来值得期待吗?
随机推荐
Problem record: FEL_ lib. c:26:10: fatal error: libusb. h: There is no such file or directory
Hash design and memory saving data structure design in redis
C#【高级篇】 C# 接口(Interface)
[frequently asked questions] modularization of browser environment and node environment
How do college students make money by programming| My way to make money in College
【常见问题】页面跨域和接口跨域
Some common functions and precautions
QT中foreach的使用
Ubuntu20.04 PostgreSQL 14 installation configuration record
Auto.js学习笔记15:autojs的UI界面基础篇2
HOOK Native API
Stc89c52/90c516rd/89c516rd DHT11 temperature and humidity sensor drive code
专升本高数(三)
【十分钟】manim安装 2022
golang bilibili直播弹幕姬
The 5-year Android development interview took 20 days to join Alibaba
Laravel9 installation locale
实用调试技巧
laravel9本地安裝
【常见问题】浏览器环境、node环境的模块化问题