Android 基于反射实现简易版ButterKnife
反射比较消耗资源,一般不推荐使用。文章来源地址https://www.toymoban.com/news/detail-689265.html
定义注解
/**
* 用于绑定元素
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindView {
@IdRes int value();
}
/**
* 定义元注解
*/
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventType {
Class methodClass(); //方法所在的Class
String methodName(); //方法名
}
/**
* 绑定点击事件
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventType(methodClass = View.OnClickListener.class, methodName = "setOnClickListener")
public @interface OnClick {
@IdRes int[] value() default {};
}
/**
* 绑定长按事件
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventType(methodClass = View.OnLongClickListener.class, methodName = "setOnLongClickListener")
public @interface OnLongClick {
@IdRes int[] value() default {};
}
定义绑定类解析注解
public class MyButterKnife {
public static void bind(Activity activity) {
//获取类中所有变量
Field[] fields = activity.getClass().getDeclaredFields();
//获取类中所有方法
Method[] methods = activity.getClass().getDeclaredMethods();
bindFields(activity, fields);
bindMethods(activity, methods);
}
/**
* 绑定变量
*
* @param activity
* @param fields
*/
private static void bindFields(Activity activity, Field[] fields) {
for (Field field : fields) {
//判断是否被@BindView注解
if (field.isAnnotationPresent(BindView.class)) {
//获取@BindView注解
BindView bindView = field.getAnnotation(BindView.class);
if (bindView != null) {
//设置访问权限
if (!field.isAccessible()) {
field.setAccessible(true);
}
//获取注解值
int id = bindView.value();
//获取View
View view = activity.findViewById(id);
try {
//通过反射设置值
field.set(activity, view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 绑定方法
*
* @param activity
* @param methods
*/
private static void bindMethods(Activity activity, Method[] methods) {
for (Method method : methods) {
//判断是否被@OnClick或@OnLongClick注解
if (method.isAnnotationPresent(OnClick.class) || method.isAnnotationPresent(OnLongClick.class)) {
//获取方法上的所有注解
Annotation[] annotations = method.getAnnotations();
//遍历注解
for (Annotation annotation : annotations) {
//获取注解的注解类型
Class<? extends Annotation> annotationType = annotation.annotationType();
//判断注解是否为@EventType
if (annotationType.isAnnotationPresent(EventType.class)) {
//获取EventType注解
EventType eventType = annotationType.getAnnotation(EventType.class);
assert eventType != null;
//获取方法的Class
Class methodClass = eventType.methodClass();
//获取方法名
String methodName = eventType.methodName();
//设置访问权限
method.setAccessible(true);
try {
//获取OnClick或OnLongClick的value值
Method valueMethod = annotationType.getDeclaredMethod("value");
//获取绑定的id
int[] viewIds = (int[]) valueMethod.invoke(annotation);
//代理对象
Object proxy = Proxy.newProxyInstance(methodClass.getClassLoader(),
new Class[]{methodClass},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
return method.invoke(activity, args);
}
});
assert viewIds != null;
//遍历id并绑定事件
for (int id : viewIds) {
//获取Activity的View
View view = activity.findViewById(id);
//获取指定方法,如setOnClickListener方法,参数类型是OnClickListener
Method clickMethod = view.getClass().getMethod(methodName, methodClass);
//执行方法
clickMethod.invoke(view, proxy);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
}
使用
public class MainActivity extends AppCompatActivity {
@BindView(R.id.textView)
TextView textView;
@BindView(R.id.imageView)
ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyButterKnife.bind(this);
textView.setText("hello");
imageView.setImageResource(R.mipmap.ic_launcher);
}
@OnClick({R.id.btn1, R.id.btn2})
public void click(View view) {
switch (view.getId()) {
case R.id.btn1:
Toast.makeText(this, "btn1 click", Toast.LENGTH_SHORT).show();
break;
case R.id.btn2:
Toast.makeText(this, "btn2 click", Toast.LENGTH_SHORT).show();
break;
}
}
@OnLongClick({R.id.btn1, R.id.btn2})
public boolean longClick(View view) {
switch (view.getId()) {
case R.id.btn1:
Toast.makeText(this, "btn1 longClick", Toast.LENGTH_SHORT).show();
break;
case R.id.btn2:
Toast.makeText(this, "btn2 longClick", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
}
代码下载
文章来源:https://www.toymoban.com/news/detail-689265.html
到了这里,关于Android 基于反射实现简易版ButterKnife的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!