附上github地址:https://github.com/yuanmingsun/easyannotion.git
注解是java1.5開始的。在java框架中比如spring,hibernate中都大量用到了注解。android中如retrofit和butterkinfe都用到了注解。比如我們在android開發(fā)中大量用到了findviewbyid,我們可以使用注解來生成findviewbyid,簡化自己的工作量。
注解的分類
元注解包括@Retention,@Target,@Document,@Inherited
1. @Retention:指該注解保留的時間長短,RetentionPolicy是一個enum類型,取值分別為SOURCE,CLASS,RUNTIME
? 1).@Retention(RetentionPolicy.SOURCE):注解僅存在于源碼中。
? 2).@Retention(RetentionPolicy.ClASS):默認的保留方式,注解存在于class字節(jié)碼中,但是運行時無法獲取。
? 3).@Retention(RetentionPolicy.RUNTIME)注解可以在運行時通過反射得到。
2.@Target:指注解可以注解的元素范圍.取值可以為TYPE類,METHOD方法,CONSTRUCTOR構(gòu)造函數(shù),FIELD字段等。如果@Target注解沒有定義,那么注解的范圍是所有。
3.@Document:指明該注解可以被javadoc此類的工具文檔化
4.@Inherited: 指明該注解類型可以被自動繼承。
內(nèi)建注解
1.@override :想要重寫父類的方法時,通過這個注解告訴編譯器我們要重寫這個方法。如果父類中方法變化那么編譯器就會告警。
2.@Deprecated:某一個方法不被推薦使用時,可以用這個注解來聲明。
3.SupressWarning告訴編譯器忽略特定的警告信息。保留時常為soure,會被編譯器丟掉.
4.android的內(nèi)建注解就比較多了。如@StringRes,@Nullable。在谷歌提供的support-annotions庫中。
說了這么多,我們開始打造自己的注解框架把。首先我們來打造一個編譯時注解框架。
1.首先新建兩個注解,一個是bindId.class,用于綁定activity和view,一個是onClick.class用于綁定點擊事件
然后我們?nèi)ネㄟ^反射來獲取拿到注解,綁定findviewbyid和onclick
public class BindApi {
public static void init(Activity obj) {
bindViewId(obj);
? ? ? ? bindOnClick(obj);
? ? }
private static? void bindOnClick(final Activity obj) {
Class cls=obj.getClass();
? ? ? Method [] methods=cls.getMethods();
? ? ? for(final Method method :methods)
{
if(method.isAnnotationPresent(OnClick.class))
{
OnClick onClick=method.getAnnotation(OnClick.class);
? ? ? ? ? ? ? int []ids=onClick.value();
? ? ? ? ? ? ? for(int id :ids)
{
Method method2 =null;
? ? ? ? ? ? ? ? ? try {
method2 = cls.getMethod("findViewById", int.class);
? ? ? ? ? ? ? ? ? }catch (NoSuchMethodException e) {
e.printStackTrace();
? ? ? ? ? ? ? ? ? }
method2.setAccessible(true);
? ? ? ? ? ? ? ? ? View v=null;
? ? ? ? ? ? ? ? ? try {
v = (View)method2.invoke(obj, id);
? ? ? ? ? ? ? ? ? }catch (IllegalAccessException e) {
e.printStackTrace();
? ? ? ? ? ? ? ? ? }catch (InvocationTargetException e) {
e.printStackTrace();
? ? ? ? ? ? ? ? ? }
v.setOnClickListener(new View.OnClickListener() {
@Override
? ? ? ? ? ? ? ? ? ? ? public void onClick(View v) {
method.setAccessible(true);
? ? ? ? ? ? ? ? ? ? ? ? ? try {
method.invoke(obj,v);
? ? ? ? ? ? ? ? ? ? ? ? ? }catch (IllegalAccessException e) {
e.printStackTrace();
? ? ? ? ? ? ? ? ? ? ? ? ? }catch (InvocationTargetException e) {
e.printStackTrace();
? ? ? ? ? ? ? ? ? ? ? ? ? }
}
});
? ? ? ? ? ? ? }
}
}
}
private static void bindViewId(Activity obj) {
Class cls = obj.getClass();
? ? ? ? if (cls.isAnnotationPresent(BindId.class)) {
//這里使用了反射的方法來調(diào)用setContentView
? ? ? ? ? ? BindId mId = cls.getAnnotation(BindId.class);
? ? ? ? ? ? int id = mId.value();
? ? ? ? ? ? try {
Method method = cls.getMethod("setContentView", int.class);
? ? ? ? ? ? ? ? method.setAccessible(true);
? ? ? ? ? ? ? ? method.invoke(obj, id);
? ? ? ? ? ? }catch (NoSuchMethodException e) {
e.printStackTrace();
? ? ? ? ? ? }catch (IllegalAccessException e) {
e.printStackTrace();
? ? ? ? ? ? }catch (InvocationTargetException e) {
e.printStackTrace();
? ? ? ? ? ? }
//這里直接調(diào)用findviewbyid
? ? ? ? ? ? Field[] fields = cls.getDeclaredFields();
? ? ? ? ? ? for (Field field : fields) {
if (field.isAnnotationPresent(BindId.class)) {
BindId mId2 = field.getAnnotation(BindId.class);
? ? ? ? ? ? ? ? ? ? int id2 = mId2.value();
? ? ? ? ? ? ? ? ? ? try {
Method method = cls.getMethod("findViewById", int.class);
? ? ? ? ? ? ? ? ? ? method.setAccessible(true);
? ? ? ? ? ? ? ? ? ? View view = (View)method.invoke(obj,id2);
? ? ? ? ? ? ? ? ? ? field.setAccessible(true);
? ? ? ? ? ? ? ? ? ? ? ? field.set(obj, view);
? ? ? ? ? ? ? ? ? ? }catch (IllegalAccessException e) {
e.printStackTrace();
? ? ? ? ? ? ? ? ? ? }catch (NoSuchMethodException e) {
e.printStackTrace();
? ? ? ? ? ? ? ? ? ? }catch (InvocationTargetException e) {
e.printStackTrace();
? ? ? ? ? ? ? ? ? ? }
}
}
}
}
}
最后,在activity使用