基于上一篇Type1,我们现在第二种注解类型,主要还是用法上更趋向butterknife.
@OnClicks(R.id.testSB)
public void fucnSbs(View view){
sb.setText("fuck sb 3");
}
package com.example.mylibrary;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Author:hl
* Time: 2018/5/25 10:27
* Des: This is OnClick
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClicks {
int value(); ///< 控件id
}
2.实现注解翻译,主要是Method的获取和使用
///< 1\. 获取Method方法数组
Method[] methods = classObj.getDeclaredMethods();
for (final Method method : methods){
///< 2\. 判断是否添加了OnClicks注解
if (method.isAnnotationPresent(OnClicks.class)){
///< 3.获取注解实例对象
final OnClicks onClicks = method.getAnnotation(OnClicks.class);
int viewId = onClicks.value();
try {
///< 4\. 获取控件
Method methodFd = classObj.getMethod("findViewById", int.class);
final View viewObj = (View)methodFd.invoke(context, viewId);
///< 5.设置点击事件,执行方法
viewObj.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
method.invoke(context, viewObj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
3.多个参数版本来一个吧
3.1 修改下OnClicks.java
package com.example.mylibrary;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Author:hl
* Time: 2018/5/25 10:27
* Des: This is OnClick
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClicks {
int[] value(); ///< 控件id
}
///< 1\. 获取Method方法数组 - OnClicks
Method[] methods = classObj.getDeclaredMethods();
for (final Method method : methods){
///< 2\. 判断是否添加了OnClicks注解
if (method.isAnnotationPresent(OnClicks.class)){
///< 3.获取注解实例对象
final OnClicks onClicks = method.getAnnotation(OnClicks.class);
int[] viewId = onClicks.value();
for (int vId : viewId){
try {
///< 4\. 获取控件
Method methodFd = classObj.getMethod("findViewById", int.class);
final View viewObj = (View)methodFd.invoke(context, vId);
///< 5.设置点击事件,执行方法
viewObj.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
method.invoke(context, viewObj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
@OnClicks({R.id.testSB, R.id.testSB2})
public void fucnSbs(View view){
sb.setText("fuck sb 3");
}
3.4 记得增加一个控件activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/testSB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/testSB2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.758" />
</android.support.constraint.ConstraintLayout>
3.4.1 搞定! 这里我把布局粘贴出来了?想提前强调下app:layout_constraintVertical_bias这个属性,这就是约束布局的魅力。真正了解了约束布局,相信可以把布局做得更简化!目前正在利用约束布局重构现有项目,后面分享一下!

总结一下,其实和上一篇没太多变化,无外乎就是我们提前获取到了点击事件的Method,进而去执行,其他逻辑还是一样。下面我们尝试把下面这一段做封装,利用到动态代理的方式去改造一下! So,下一步研究动态代理...
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
method.invoke(context, viewObj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
网友评论