为了在android开发中省去一些重复的代码输入,我们现在都在使用butterknife**这样的框架,进行代码的简化。使用这种框架能提供我们很多的方便,但是我们也要了解它的实现原理和方法。
(1)用的知识
1.使用了java中的自定义注释(Annotation)
2.使用了反射原理(反射原理大家可以在网上搜索学习)
(2)Annotation介绍
1.Annotation是用那修饰类,属性,方法。
2.元注释:是专用来注释其他注释。
//元注释的格式如下
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface onClick {
int[] value() default {};
}
大致了解了元注释的实现,我们来看下元格式的基本语法。
元注释分4种:
1.@Target :表示Annotation可以用在什么地方
它的取值为:

2.@Retention:表示什么级别保持注释信息
它的取值为:

3.@Documented:表示在Javadocs中包含这个注解。
4.@Inherited :表示允许子类继承父类中的注解。
3.实现流程
实现流程:定义一个注释类,在使用的地方调用,关键是通过反射的方法调用系统中的对应函数。
下面通过自定义android中的设置布局的例子,了解其流程:

1.定义注释类(ContentView.java)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
int value();
}
2.activity中调用注释
@ContentView(R.layout.inject_view)
public class InjectActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewInjectUtils.injectContentView(this);
}
}
3.关键步骤实现反射回调
public class ViewInjectUtils {
//设置布局
public static void injectContentView(Activity activity) {
Class a = activity.getClass();
if (a.isAnnotationPresent(ContentView.class)) {
// 得到activity这个类的ContentView注解
ContentView contentView = (ContentView) a.getAnnotation(ContentView.class);
// 得到注解的值
int layoutId = contentView.value();
// 使用反射调用setContentView
try {
Method method = a.getMethod("setContentView", int.class);
method.setAccessible(true);
method.invoke(activity, layoutId);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
4.反射回调的实现
@Target取值不同实现回调时候调用的方法就不同,下面介绍下
ElementType.TYPE,ElementType.METHOD,ElementType.FIELD回调的方法
(1)ElementType.TYPE定义类,接口和enum声明。在android中,可以认为是定义activity中的布局文件。

(2)ElementType.FIELD定义域声明。在android中,可以认为是定义activity中每个控件。

(3)ElementType.METHOD定义方法。在android中,可以认为是定义activity中点击事件。
1.定义注释类

2.定义一个注释类型声明

3.调用事件

使用了动态代理

网友评论