您的位置:首页 > Web前端

ButterKinfe原理,并简单仿照ButterKinfe定义自己的ButterKnife

2016-04-14 10:33 302 查看
以7.0.0版本进行分析,其本质就是注解加反射

在使用butterKinfe的时候先绑定,其实就是获得注解的对象,之后扫描这个对象的字节码的所有的filed和method,符合我们注解的就保存下来

当符合filed的时候,就给filed通过反射赋值

当符合method的时候,就给method对应的id的view设置监听,之后回调method方法

接下来我们手把手定义自己的ButterKinfe

先定义注解bind,用来减少findviewbyid的

`package com.example.admin.butterkinfe.butterkinfe;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Created by admin on 2016/4/14.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Bind {
int value();
}


`

* 之后定义我们的OnClick注解

`package com.example.admin.butterkinfe.butterkinfe;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Created by admin on 2016/4/14.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OnClick {
int[] value();
}


`

* 接下来也就是我们的butterKinfe主类,在使用butterKinfe的时候,需要先bind

`package com.example.admin.butterkinfe.butterkinfe;

import android.app.Activity;
import android.view.View;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
* Created by admin on 2016/4/14.
*/
public class ButterKinfe {
private static Map<Integer,View> hashMap=new HashMap<>();
public static void bind(Object object) {
//类,扫描属性和方法,之后给这个方法复制
scannner(object);
}

private static void scannner(Object object) {
scannerFiled(object);//扫描所有的field,找到符合条件的赋值
scannerMethod(object);//扫描所有的method,找的符合条件的进行回调
}

private static void scannerMethod(final Object object) {
Method[] methods = object.getClass().getDeclaredMethods();
for(final Method m:methods){
if(m.isAnnotationPresent(OnClick.class)){
m.setAccessible(true);

OnClick annotation = m.getAnnotation(OnClick.class);
int[] id= annotation.value();
for(int i=0;i<id.length;i++){
final View view=  hashMap.get(i);
if(view!=null){
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
m.invoke(object,v);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
}else{
Activity a= (Activity) object;
final View temp=a.findViewById(id[i]);
temp.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
m.invoke(object,v);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
}
}
}
}
}

private static void scannerFiled(Object object) {
Field[] fields = object.getClass().getDeclaredFields();
for (Field f : fields) {
boolean annotationPresent = f.isAnnotationPresent(Bind.class);
if (annotationPresent) {
f.setAccessible(true);
Bind bind = f.getAnnotation(Bind.class);
int id = bind.value();
Activity a = (Activity) object;
try {
View view= a.findViewById(id);
hashMap.put(id,view);
f.set(object,view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}

}


`

* 方法其实很简单,就是扫描bind对象的所有的注解,之后反射赋值或者反射调用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: