代码示例分析
通过简单的代码实现butterknife的功能,用来强化注解,反射,动态代理的理解和应用
1.调用用代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//掉用实现类
Butterknife.bind(this);
}
@onclick({R.id.bt_7,R.id.bt_8})
public void onclick(View view){
switch (view.getId()){
case R.id.bt_7:
Log.e("lzl","按钮7点击");
break;
case R.id.bt_8:
Log.e("lzl","按钮8点击");
break;
}
}
@onlongclick({R.id.bt_7,R.id.bt_8})
public boolean onlongclick(View view){
switch (view.getId()){
case R.id.bt_7:
Log.e("lzl","按钮7长按");
break;
case R.id.bt_8:
Log.e("lzl","按钮8长按");
break;
}
return false;
}
2.自定义注解
/**
* 这个是注解的注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Envtype {
String listenerSetter();
Class ListenerType();
}
/**
*这个是点击事件注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Envtype(listenerSetter = "setOnClickListener", ListenerType = View.OnClickListener.class)
public @interface onclick {
int[] value();
}
/**
* 这个是长按注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Envtype(listenerSetter = "setOnLongClickListener",ListenerType = View.OnLongClickListener.class)
public @interface onlongclick {
int[] value();
}
3.butterknif的实现类
public class Butterknife {
public static void bind(MainActivity mainActivity) {
//1.拿到class对象,
Class<? extends MainActivity> mainclass = mainActivity.getClass();
//2.获取到所有的方法
Method[] methods= mainclass.getDeclaredMethods();
//3.便利所有方法
for (Method method : methods) {
Annotation[] annotation = method.getAnnotations();
//1.遍历方法上的所有注解
for (Annotation annotation1 : annotation) {
//2.获取注解的class对象
Class<? extends Annotation> annotationType = annotation1.annotationType();
//3.判断当前的注解是不是envtype注解。
if(annotationType.isAnnotationPresent(Envtype.class)){
//4.是的话获取注解上的参数。
Envtype envtype = annotationType.getAnnotation(Envtype.class);
String listenerSetter = envtype.listenerSetter();
Class listenerType = envtype.ListenerType();
//5.通过反射调用方法获取注解里的参数
try {
Method valueMethod = annotationType.getDeclaredMethod("value");
//参数是哪个对象掉用此方法
int[] value = (int[]) valueMethod.invoke(annotation1);
method.setAccessible(true);
//6.通过动态代理生成listenerType对应的接口对象。
Object proxy = Proxy.newProxyInstance(mainActivity.getClassLoader(), new Class[]{listenerType}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
//此处掉用的是activity里的方法,所以第一个对象是activity
return method.invoke(mainActivity,args);
}
});
//7.找到对应的控件设置相应的回调
for (int i : value) {
View view = mainActivity.findViewById(i);
//获取控件的class文件,通过反射掉用里面的方法
Method setter = view.getClass().getMethod(listenerSetter,listenerType);
setter.invoke(view,proxy);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
}