
注解是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。
在运行时读取需要使用Java反射机制进行处理。
一、注解的作用:
注解将一些本来重复性的工作,变成程序自动完成,简化和自动化该过程。比如用于生成Java doc,比如编译时进行格式检查,比如自动生成代码等,用于提升软件的质量和提高软件的生产效率。
二、注解都有哪些
1、Java提供了四种元注解,专门负责新注解的创建工作,即注解其他注解。
@Target
定义了Annotation所修饰的对象范围,取值:
ElementType.CONSTRUCTOR:用于描述构造器
ElementType.FIELD:用于描述域
ElementType.LOCAL_VARIABLE:用于描述局部变量
ElementType.METHOD:用于描述方法
ElementType.PACKAGE:用于描述包
ElementType.ParaMETER:用于描述参数
ElementType.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention
定义了该Annotation被保留的时间长短,取值:
- RetentionPoicy.soURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;用于做一些检查性的 *** 作,比如 @OverrIDe 和 @SuppressWarnings
- RetentionPoicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;用于在编译时进行一些预处理 *** 作,比如生成一些辅助代码(如 ButterKnife)
- RetentionPoicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;用于在运行时去动态获取注解信息。
@documented
标记注解,用于描述其它类型的注解应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化,不用赋值。
@inherited
标记注解,允许子类继承父类的注解。 这里一开始有点理解不了,需要断句一下,允许子类继承父类的注解。
2、AndroID SDK内置的注解
AndroID SDK 内置的注解都在包com.androID.support:support-annotations里,下面以'com.androID.support:support-annotations:25.2.0'为例
资源引用限制类:用于限制参数必须为对应的资源类型
@AnimRes @AnyRes @ArrayRes @AttrRes @BoolRes @colorRes等
线程执行限制类:用于限制方法或者类必须在指定的线程执行
@AnyThread @BinderThread @MainThread @UiThread @WorkerThread
参数为空性限制类:用于限制参数是否可以为空
@NonNull @Nullable
类型范围限制类:用于限制标注值的值范围
@floatRang @IntRange
类型定义类:用于限制定义的注解的取值集合
@IntDef @StringDef
其他的功能性注解:
@CallSuper @CheckResult @colorInt @Dimension @Keep @Px @RequiresAPI @RequiresPermission @RestrictTo @Size @VisibleForTesting
3、自定义注解。。。。
三、如何使用AndroID Annotation
build.gradle
dependencIEs {
androIDTestCompile('com.androID.support:support-annotations:26.1.0') {
force = true
}
}
举例子:
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface BtnOnClick { int[] value();}
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface LayoutInject { int value() default -1;}
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface OnClick { int value();}
@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface VIEwByID { int value();}
public class AnnotationParse { private static AnnotationParse instance; public static AnnotationParse getInstance() { if (instance == null) { synchronized (AnnotationParse.class) { if (instance == null) { instance = new AnnotationParse(); return instance; } } } return instance; } public voID bind(Activity activity) throws illegalaccessexception { try { injectLayout(activity); bindVIEw(activity); bindOnClick(activity); injectEvent(activity); } catch (Exception ex) { } } private static voID bindVIEw(Activity activity) throws illegalaccessexception { //1、获取字节码 Class<? extends Activity> aClass = activity.getClass(); //2、获取Activity中变量 FIEld[] declaredFIEld = aClass.getDeclaredFIElds(); for (FIEld fIEld : declaredFIEld) { //设置允许暴力反射 fIEld.setAccessible(true); //3、获取变量上的注释 VIEwByID annotation = fIEld.getAnnotation(VIEwByID.class); if (annotation != null) { //4、获取注释上的值 int ID = annotation.value(); //5、通过ID获取控件 VIEw vIEw = activity.findVIEwByID(ID); //6、控件赋值给变量 fIEld.set(activity, vIEw); } } } //对OnClick注解的“解释” private static voID bindOnClick(final Activity activity) { //1、获取字节码对象 final Class<? extends Activity> aClass = activity.getClass(); //2、获取所有的方法 Method[] declaredMethods = aClass.getDeclaredMethods(); //3、遍历所有的方法 for (final Method method : declaredMethods) { method.setAccessible(true); //4、获取方法上的注释 OnClick annotation = method.getAnnotation(OnClick.class); if (annotation != null) { int ID = annotation.value(); VIEw vIEw = activity.findVIEwByID(ID); vIEw.setonClickListener(new VIEw.OnClickListener() { @OverrIDe public voID onClick(VIEw v) { try { //执行注解的方法 method.invoke(activity, null); } catch (illegalaccessexception e) { e.printstacktrace(); } catch (InvocationTargetException e) { e.printstacktrace(); } } }); } } } private static voID injectEvent(final Activity activity) { Class<? extends Activity> clazz = activity.getClass(); Method[] methods = clazz.getDeclaredMethods(); for (final Method method2 : methods) { BtnOnClick click = method2.getAnnotation(BtnOnClick.class); if (click != null) { int[] vIEwID = click.value(); method2.setAccessible(true); Object Listener = Proxy.newProxyInstance(VIEw.OnClickListener.class.getClassLoader(), new Class[]{VIEw.OnClickListener.class}, new InvocationHandler() { @OverrIDe public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method2.invoke(activity, args); } }); try { for (int ID : vIEwID) { VIEw v = activity.findVIEwByID(ID); Method setClickListener = v.getClass().getmethod("setonClickListener", VIEw.OnClickListener.class); setClickListener.invoke(v, Listener); } } catch (Exception e) { e.printstacktrace(); } } } } private static int mLayoutID = -1; /** * 注解布局Layout ID */ private static voID injectLayout(Activity activity) { Class<?> clazz = activity.getClass(); if (clazz.getAnnotations() != null) { if (clazz.isAnnotationPresent(LayoutInject.class)) { LayoutInject inject = clazz.getAnnotation(LayoutInject.class); mLayoutID = inject.value(); activity.setContentVIEw(mLayoutID); } } }}
@LayoutInject(R.layout.activity_main)public class MainActivity extends AppCompatActivity { @VIEwByID(R.ID.tvname) TextVIEw tvname; @VIEwByID(R.ID.tvAge) TextVIEw tvAge; @VIEwByID(R.ID.tvGender) TextVIEw tvGender; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentVIEw(R.layout.activity_main); try { AnnotationParse.getInstance().bind(this); } catch (illegalaccessexception e) { e.printstacktrace(); } tvname.setText("测试名字"); tvAge.setText("28"); tvGender.setText("男"); } @BtnOnClick({R.ID.tvname, R.ID.tvAge, R.ID.tvGender}) public voID btnOnClick(VIEw vIEw) { switch (vIEw.getID()) { case R.ID.tvname: tvname.setText("华山论剑"); break; case R.ID.tvAge: tvAge.setText("四百多岁"); break; case R.ID.tvGender: tvGender.setText("女"); break; } } @OnClick(R.ID.tvname) public voID textOnClick() { tvname.setText("华山论剑"); }}总结
以上是内存溢出为你收集整理的Android annotation全部内容,希望文章能够帮你解决Android annotation所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)