注解(Annotations)使用和自定义

本博客是一个纯技术交流博客,写出来的文章是帮大家解决一些问题,或让大家有个参考和思路,更多技术分享请关注http://blog.36dr.net,有任何问题可与我邮件dr.kalen@yahoo.com

前言

Android默认提供Annotation框架同时网络也冲刺着各种Android Annotation框架,诸如此类框架很多,但是用过之后使用都比较复杂,同时还有一些无法避免的bug。如在Android开发时经常会遇到获得界面中的View使用方法findViewById特别是在Adapter中需要对所有使用的组件变量赋值,每次调用findViewById就显得多余的开发,若采用注解则会方便开发,精简代码的结构和提示代码阅读性,当然由于Annotation是反射机制设置变量值,则在性能上会相对于普通方式差,在此硬件比拼的时代,此性能几乎可以忽略。

原理和自定义

以前言中提到Android开发多次调用findViewById方法的困惑,我们通过自定义Annotation来解决此问题。如下:

  1. 定义注解类:
@Target(ElementType.FIELD)//表示用在字段上  
@Retention(RetentionPolicy.RUNTIME)//表示在生命周期是运行时  
public @interface ViewInject {  
    int value() default 0;  //返回注解中的信息
}  
  1. 定义一个BaseActivity作为需要注解的基类,用于实现注解的功能(反射注入数据)
public abstract class BaseActivity extends FragmentActivity {  
    /**
     * get content view layout id
     *  
     * @return
     */  
    public abstract int getLayoutId();  


    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(getLayoutId());  
        autoInjectAllField();  
    }  
    /**
     * 解析注解
     */  
    public void autoInjectAllField() {  
        try {  
            Class<?> clazz = this.getClass();  
            Field[] fields = clazz.getDeclaredFields();//获得Activity中声明的字段  
            for (Field field : fields) {  
                // 查看这个字段是否有我们自定义的注解类标志的  
                if (field.isAnnotationPresent(ViewInject.class)) {  
                    ViewInject inject = field.getAnnotation(ViewInject.class);  
                    int id = inject.value();  
                    if (id > 0) {  
                        field.setAccessible(true);  
                        field.set(this, this.findViewById(id));//给我们要找的字段设置值  
                    }  
                }  
            }  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        } catch (IllegalArgumentException e) {  
            e.printStackTrace();  
        }  
    }  
}  
  1. 注解使用
public class TestActivity extends BaseActivity {  

    @ViewInject(R.id.claim_statement)  
    private WebView mWebView;  


    @Override  
    public int getLayoutId() {  
        // TODO Auto-generated method stub  
        return R.layout.activity_claim;  
    }  

}  

详细说明

系统中方法经常会使用@Override和@Deprecated注解,我们看看系统注解如何定义:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

我们发现这两个注解用到了其他注解@Target,@Retention,@Documented;这些注解称之为元注解。

  1. @Target用于标明注解用于的地方,它的值是一个枚举值:
  • CONSTRUCTOR:用于描述构造器
  • FIELD:用于描述域
  • LOCAL_VARIABLE:用于描述局部变量
  • METHOD:用于描述方法
  • PACKAGE:用于描述包
  • PARAMETER:用于描述参数
  • TYPE:用于描述类、接口(包括注解类型) 或enum声明
  1. @Retention用于描述注解的生命周期即在什么情况有效,它的值:
  • SOURCE:在源文件中有效(即源文件保留编译时忽略)
  • CLASS:在class文件中有效(即class保留JVM忽略)
  • RUNTIME:在运行时有效(即运行时保留)
  1. @Documented表明这个注解应该被javadoc工具记录。

因此当我们定义的注解中:

@Target(ElementType.FIELD)//表示用在字段上  
@Retention(RetentionPolicy.RUNTIME)//表示在生命周期是运行时  
public @interface ViewInject {  
    int value() default 0;  //返回注解中的信息

    String name() default "default name"
}  

就很好解释了,ViewInject注解是用于变量并且运行时有效,用于获得注解中的内容,内容信息为int并且默认为0.

注解类中方法value()表示获取注解中默认文字比如@ViewInject(R.id.name)获取的R.id.name的值,如果是name或则其他方法,则表示需要在注解中使用属性才能获取。及获取@ViewInject(name="name")中的name属性值。

由此,我们可以根据自己喜好,自己的功能需要,自定义合适项目的注解和注解的解析方式。
Android 注解请学习“Android Annotation”框架。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,612评论 5 471
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,345评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,625评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,022评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,974评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,227评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,688评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,358评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,490评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,402评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,446评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,721评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,802评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,013评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,504评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,080评论 2 341

推荐阅读更多精彩内容