当前位置:网站首页>利用反射整合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);
}
}
边栏推荐
- *Write a program to initialize a string object with a vector < char> container*/
- [0x0] open questions left by the principal
- MySQL performance optimization (5): principle and implementation of master-slave synchronization
- Number of students from junior college to Senior College (4)
- MySQL performance optimization (6): read write separation
- Redis高并发分布式锁(学习总结)
- 51 single chip microcomputer indoor environment monitoring system, mq-2 smoke sensor and DHT11 temperature and humidity sensor, schematic diagram, C programming and simulation
- 问题记录:fel_lib.c:26:10: fatal error: libusb.h: 没有那个文件或目录
- Tidb 6.0: making Tso more efficient tidb Book rush
- Redis is used in Windows system
猜你喜欢

MySQL performance optimization (5): principle and implementation of master-slave synchronization

SDS understanding in redis

Mathematical solution of Joseph Ring

Play with algorithm interview together, nanny level strategy (with high-definition codeless algorithm summary map), recommended collection

General paging (2)

An article to get you started VIM

Gulang bilibilibili Live Screen Jackie

F1C100S自制开发板调试过程
![[ten minutes] manim installation 2022](/img/54/7b895d785c7866271f06ff49cb20aa.png)
[ten minutes] manim installation 2022

golang bilibili直播彈幕姬
随机推荐
HOOK Native API
If you can tell whether the external stock index futures trading platform I am trading is formal and safe?
Knowledge points of 2022 system integration project management engineer examination: software quality assurance and quality evaluation
Simple custom MVC optimization
[0x0] 校长留的开放问题作业
51 single chip microcomputer indoor environment monitoring system, mq-2 smoke sensor and DHT11 temperature and humidity sensor, schematic diagram, C programming and simulation
广播模块代码在autojs4.1.1版本运行正常,但在pro7.0版本上运行报错(未解决)
Are you a "social bull" or a "social terrorist" in the interview?
C # [advanced part] C # multithreading
Redis is used in Windows system
C#【高级篇】 C# 匿名方法【待补充Lambda表达式。。。】
How to realize remote collaborative office, keep this strategy!
124 articles in total! Motianlun "high availability architecture" dry goods document sharing (including Oracle, mysql, PG)
4-5 count words and spaces (15 points)
51单片机的室内环境监测系统,MQ-2烟雾传感器和DHT11温湿度传感器,原理图,C编程和仿真
From 2500 a month, no one wants to go to the programming road of the technical director of a large factory | my ten years
Play with algorithm interview together, nanny level strategy (with high-definition codeless algorithm summary map), recommended collection
Reasons for MySQL master-slave database synchronization failure
Arrangement of language resources of upgraded version
The 5-year Android development interview took 20 days to join Alibaba