您的位置:首页 > 移动开发 > Android开发

学习如何自定义Android注解

2016-11-22 20:39 211 查看
之前,在项目经常运用annotation这个注解框架来方便自己的开发,开发非常快。今天闲来无事,回顾下。Android的注解简单来说就是通过java的反射机制来完成。那么,我们直接看代码吧我们先定义一个BindId的注解packagecom.example.boom.annotationproject.annotation;importjava.lang.annotation.Documented;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;/***CreatedbyBoomon2016/11/21.*/@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public@interfaceBindId{intvalue()default0;}在定义一个OnClick的注解packagecom.example.boom.annotationproject.annotation;importjava.lang.annotation.Documented;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;/***CreatedbyBoomon2016/11/21.*/@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public@interfaceOnClick{intvalue()default0;}其中,我们看到的 @Documented @Retention @Target都是java自带的,而@interfaceBindId即@BindId就是我们自定义的注解。总的来说就是用java自带的那些小单元注解构建我们自定义的注解。这是我的个人看法。那光有定义肯定不行,我们还需要具体。类 MyAnnotationpackagecom.example.boom.annotationproject.annotation;importandroid.app.Activity;importandroid.view.View;importjava.lang.reflect.Field;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;/***CreatedbyBoomon2016/11/21.*/publicclassMyAnnotation{publicstaticvoidinit(Activityactivity){setBindIdWithViewAnnotation(activity);getOnClick(activity);}privatestaticvoidsetBindIdWithViewAnnotation(Activityactivity){Classclazz=activity.getClass();Field[]fields=clazz.getDeclaredFields();for(Fieldfield:fields){BindIdbindId=field.getAnnotation(BindId.class);if(bindId!=null){intId=bindId.value();try{field.setAccessible(true);field.set(activity,activity.findViewById(Id));}catch(IllegalAccessExceptione){e.printStackTrace();}}}}privatestaticvoidgetOnClick(finalActivityactivity){Classclazz=activity.getClass();Method[]methods=clazz.getDeclaredMethods();for(finalMethodmethod:methods){OnClickonclick=method.getAnnotation(OnClick.class);if(onclick!=null&&onclick.value()!=0){Viewv=activity.findViewById(onclick.value());if(v==null){return;}v.setOnClickListener(nec016wView.OnClickListener(){@OverridepublicvoidonClick(Viewv){try{method.setAccessible(true);method.invoke(activity,v);}catch(IllegalAccessExceptione){e.printStackTrace();}catch(InvocationTargetExceptione){e.printStackTrace();}}});}}}}
那怎么用呢?packagecom.example.boom.annotationproject;importandroid.app.Activity;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.TextView;importandroid.widget.Toast;importcom.example.boom.annotationproject.annotation.BindId;importcom.example.boom.annotationproject.annotation.OnClick;importcom.example.boom.annotationproject.annotation.MyAnnotation;publicclassMainActivityextendsActivity{@BindId(R.id.tv)TextViewtv;@OnClick(R.id.tv)voidshow(Viewv){Toast.makeText(this,"自定义注解成功",Toast.LENGTH_SHORT).show();}@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MyAnnotation.init(this);tv.setText("自定义注解");}}
Classclazz=activity.getClass();//获取类对象
Field[]fields=clazz.getDeclaredFields();//获取类中的所有属性
Method[]methods=clazz.getDeclaredMethods();//获取类中的所有方法
BindIdbindId=field.getAnnotation(BindId.class);//找到对应的注解
OnClickonclick=method.getAnnotation(OnClick.class);//找到对应的注解
那么他们是怎么找的呢?
@Target(ElementType.FIELD)//目标是属性
@Target(ElementType.METHOD)//目标是方法
那for循环有什么用?循环遍历类中的所有属性或者方法我们再来看看,他们为什么这么写?
field.set(activity,activity.findViewById(Id));
使用时:
@BindId(R.id.tv)TextViewtv;
method.invoke(activity,v);
使用时:
show(Viewv)
第二个参数都是回传的。其中,我们需要注意的是:
method.setAccessible(true);//如果不写这句话并且show()方法不设置为public会报IllegalAccessException的错method.invoke(activity,v);//如果invoke方法的第二个参数不写,使用的时候show()就不用定义,简而言之就是二个参数是回传的。
我的github项目下载地址:https://github.com/BoomGit/AnnotationProject.git
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: