关于java注解

刚进公司的时候,clone了花果山的代码下来看,很幸运,这个项目刚刚开始,我可以把leo的框架先完整的看一遍而不受其他细节的影响,Leo写了非常多的基础类,非常多的抽象类,整个app的网络请求,加载图片,ListView加载数据都已经封装好,在这个基础上,我们的代码一下简化了不少,但另一方面,我们需要去理解Leo写的这些类到底为我们做了什么,当我开始找所有的基类的时候,我发现有些类根本在project里找不到,甚至连第三方类库也找不到,后来在Leo帮忙配置环境的时候我才知道,原来这些类都在远程库里,需要gradle去下载相应的依赖(之前都是用的Eclipse开发,Android studio最近才用,所以gradle我并不熟悉),这次就不谈gradle了,因为让我觉得神奇的代码其实是Leo写的注解,java算是白学了,每次看书看到注解的时候都以为只是简单的注释没必要看,直到看到Leo用@ViewById代替findViewById方法让代码看上去简洁清晰的时候我知道我该看看Java的注解了:

java为我们提供了元注解,元注解负责注解其他注解:@Target,@Retention,@Documented,@Inherited,根据这四个我们可以自定义自己的注解

我们只讨论前两个,因为前两个比较常用,也是Leo使用的

1.@Target说明了自定义注解修饰的对象,取值(ElementType)可以是

1.CONSTRUCTOR:用于描述构造器

2.FIELD:用于描述域

3.LOCAL_VARIABLE:用于描述局部变量

4.METHOD:用于描述方法

5.PACKAGE:用于描述包

6.PARAMETER:用于描述参数

7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

2.@Retention说明了自定义注解保留的时间,取值(RetentionPoicy)可以是

1.SOURCE:在源文件中有效(即源文件保留)

2.CLASS:在class文件中有效(即class保留)

3.RUNTIME:在运行时有效(即运行时保留)

知道这两个后,我们可以自定义注解了,自定义注解一共三步:一是定义注解,二是定义注解处理器,三是使用注解。

一.定义注解

为了和接口区分,Java在interface关键字前加一个@符号来定义注解

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewById {
    int value() default -1;

    int id() default -1;
}

可以看到Leo自定义ViewById注解修饰的对象是域,并且是在运行是有效,value表示域的值


二.定义注解处理器

    public static int inject(Object object, View view) {
        int injectCount = 0;
        Field[] fields = object.getClass().getDeclaredFields();
        Field[] arr$ = fields;
        int len$ = fields.length;

        for(int i$ = 0; i$ < len$; ++i$) {
            Field field = arr$[i$];
            field.setAccessible(true);

            try {
                if(field.get(object) == null) {
                    ViewById e = (ViewById)field.getAnnotation(ViewById.class);
                    if(e != null) {
                        int viewId = e.value() != -1?e.value():e.id();
                        if(viewId != -1) {
                            field.set(object, view.findViewById(viewId));
                            ++injectCount;
                        }
                    }
                }
            } catch (IllegalAccessException var10) {
                var10.printStackTrace();
            } catch (IllegalArgumentException var11) {
                Log.e(TAG, "Field name : " + field.getName());
                var11.printStackTrace();
            }
        }

        return injectCount;
    }

可以看到,Leo先把对象里所有的域找出来放到一个数组,然后对数组的每一个域通过java的反射机制得到访问权限,用

ViewById e = (ViewById)field.getAnnotation(ViewById.class);
获取到该域的注解,然后用

field.set(object, view.findViewById(viewId));
为该域调用findViewById方法

三.使用注解

在BaseActivity中调用:

inject(activity, activity.getWindow().getDecorView());

之后所有继承BaseActivity的Activity中都可以直接使用

    @ViewById(R.id.name)
    private EditText mName;

这两行就代替了以下代码:

private EditText mName;
mName = findViewById(R.id.name);
而且关键是可以在Activity的域中使用,而不用在onCreate()方法中去调用findViewById方法。使代码看上去简洁清晰了许多。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值