转自:http://www.2cto.com/kf/201405/302998.html

这篇文章主要讲解注解实现findViewById的功能,首先我们来熟悉一下在java中怎么定义一个注解和解析一个注解

注解的概念是在jdk5.0中提出来的,在java.lang的包中已经定义了三个注解:Override,Deprecated,SuppressWarnings
Override相信大家非常熟悉,就是表明这个方法是改写了父类的方法
Deprecated表示在新版本的 jdk中已经不建议使用这个方法或者属性
SuppressWarning就是屏蔽掉一些警告

知道了注解的概念后,我们就来自定义注解

注解的定义和接口的接口非常像,在interface的前面多了一个@

public @interface TestPerson
{ }

千万不能把前面的@符号弄掉了,弄掉了就成了接口的定义了,上面是一个最简单注解的定义,当然注解和类一样,也可以定义属性,如下:

public @interface TestPerson
{
//name既是这个注解的属性,也是注解的方法,调用name()返回值就是name
String name() default gavin;
}

我现在想定义两个注解,一个注解用来说明某个类的意义,另一个注解用来说明类中的某个方法由谁测试的,便于追究责任,定义如下:

//用来标注某个类是用来干嘛的
public @interface ClassFunction
{
String value() default ;
} //用来标注类中的方法是被谁测试的
public @interface TestPerson
{
//name是属性而不是方法,gavin是它的默认值,在定义的时候可以不用给定默认值
String name() default gavin;
}

那么怎么限定一个注解是用在类上还是用在方法上?比如Override就是用在方法上的注解,Deprecated是既可以用在方法上面,也可以用在类上面,我们直接看看Override是怎么实现的吧

@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这种注解叫做元注解,我们分别看看它们的意思吧
Target注解的功能就是表明你这个注解是用在什么地方的,它的值是一个枚举型
 1.CONSTRUCTOR:用于描述构造器
 2.FIELD:用于描述域
 3.LOCAL_VARIABLE:用于描述局部变量
 4.METHOD:用于描述方法
 5.PACKAGE:用于描述包
 6.PARAMETER:用于描述参数
 7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

Retention注解的功能差不多说明的就是你的注解的生命周期吧,就是什么时候失效,它的值如下
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)

我就介绍这两个元注解吧,其他的感觉也用的不是很多,如果你感兴趣可以自己Google一下

那么我们就完善我们自己的注解吧

@Target(ElementType.METHOD)//作用于方法
@Retention(RetentionPolicy.RUNTIME)//在运行时有效(即运行时保留)
public @interface TestPerson
{
//name是属性而不是方法,gavin是它的默认值,在定义的时候可以不用给定默认值
String name() default gavin;
} @Target(ElementType.TYPE)//作用于类上
@Retention(RetentionPolicy.RUNTIME)//在运行时有效(即运行时保留)
public @interface ClassFunction
{
String value() default ;
}

那么我们就来使用一下我们的注解吧

@ClassFunction(用于描述一个人的基本信息)
public class Person
{
private static final String TAG = Person; @TestPerson(name=jj)
public void setName()
{ }
}

这里要说明一点就是:如果某个注解属性使用value作为名称如ClassFunction中的value,那么赋值的时候可以直接@ClassFunction(用于描述一个人的基本信息),但是如果你使用的是其他名称,那么必须@TestPerson(name=jj)这样调用

以上就是定义一个注解的过程,下面我们来解析一个注解
定义一个TestPerson注解

/**
* com.annotation.TestPerson
* @author yuanzeyao * create at 2014年5月21日 下午1:30:14
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestPerson { String name();
}

然后在Person类中加入注解

public class Person {
private static final String TAG = Person;
@TestPerson(name=gavin)
public void getName()
{ }
}

解析注解

public class Main {
private static final String TAG = Main;
public static void main(String[] args)
{
Person person=new Person();
//获得Person对应的Class
Class<person> clazz=Person.class;
try {
//找到getName方法
Method method=clazz.getMethod(getName,null);
//判断是否被TestPerson标注
if(method.isAnnotationPresent(TestPerson.class))
{
//调用getName方法
method.invoke(person, null);
//得到TestPerson注解的实例
TestPerson test=method.getAnnotation(TestPerson.class);
//获得其name属性
String name=test.name();
System.out.println(this method is test by-->+name);
}
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
}
}

已经将定义注解和解析注解讲解完了,下面来具体分析一下怎么在Android中使用注解来代替findViewById
定义一个注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView
{
//id就是控件id,在某一个控件上使用注解标注其id
int id() default -1;
}

在Activity中加入注解

public class MainActivity extends Activity
{
public static final String TAG=MainActivity;
//标注TextView的id
@InjectView(id=R.id.tv_img)
private TextView mText; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
autoInjectAllField(this);
} catch (IllegalAccessException e) {
} catch (IllegalArgumentException e) {
} if(mText!=null)
mText.setText(Hello Gavin);
} public void autoInjectAllField(Activity activity) throws IllegalAccessException, IllegalArgumentException
{
//得到Activity对应的Class
Class clazz=this.getClass();
//得到该Activity的所有字段
Field []fields=clazz.getDeclaredFields();
Log.v(TAG, fields size-->+fields.length);
for(Field field :fields)
{
//判断字段是否标注InjectView
if(field.isAnnotationPresent(InjectView.class))
{
Log.v(TAG, is injectView);
//如果标注了,就获得它的id
InjectView inject=field.getAnnotation(InjectView.class);
int id=inject.id();
Log.v(TAG, id--->+id);
if(id>0)
{
//反射访问私有成员,必须加上这句
field.setAccessible(true);
//然后对这个属性复制
field.set(activity, activity.findViewById(id));
}
}
}
} }

Android中通过注解代替findViewById方法的更多相关文章

  1. 理解Android中的注解与反射

    反射 Java反射(Reflection)定义 Java反射机制是指在运行状态中 对于任意一个类,都能知道这个类的所有属性和方法:对于任何一个对象,都能够调用它的任何一个方法和属性: 这样动态获取新的 ...

  2. android中获取root权限的方法以及原理(转)

    一. 概述 本文介绍了android中获取root权限的方法以及原理,让大家对android 玩家中常说的“越狱”有一个更深层次的认识. 二. Root 的介绍 1. Root 的目的 可以让我们拥有 ...

  3. Android中集成第三方库的方法和问题

    Android中集成第三方库的方法和问题 声明: 1. 本文參考了网上同学们的现有成果,在此表示感谢,參考资料在文后有链接. 2. 本文的重点在第三部分,是在开发中遇到的问题及解决的方法.第一,第二部 ...

  4. Android中获取文件路径的方法总结及对照

    最近在写文件存贮,Android中获取文件路径的方法比较多,所以自己也很混乱.找了好几篇博客,发现了以下的路径归纳,记录一下,以备不时之需 Environment.getDataDirectory() ...

  5. Spring Boot中@Scheduled注解的使用方法

    Spring Boot中@Scheduled注解的使用方法 一.定时任务注解为@Scheduled,使用方式举例如下 //定义一个按时间执行的定时任务,在每天16:00执行一次. @Scheduled ...

  6. Android中各种Adapter的使用方法

    1.概念 Adapter是连接后端数据和前端显示的适配器接口.是数据和UI(View)之间一个重要的纽带.在常见的View(ListView,GridView)等地方都须要用到Adapter.例如以下 ...

  7. Android中的跨进程通信方法实例及特点分析(二):ContentProvider

    1.ContentProvider简单介绍 在Android中有些数据(如通讯录.音频.视频文件等)是要供非常多应用程序使用的.为了更好地对外提供数据.Android系统给我们提供了Content P ...

  8. Android中的跨进程通信方法实例及特点分析(一):AIDL Service

    转载请注明出处:http://blog.csdn.net/bettarwang/article/details/40947481 近期有一个需求就是往程序中增加大数据的採集点,可是由于我们的Andro ...

  9. Android中的onActivityResult和setResult方法的使用

    如果你想在Activity中得到新打开Activity关闭后返回的数据,你需要使用系统提供的startActivityForResult(Intent intent,int requestCode)方 ...

随机推荐

  1. 生活life

    1.想办法努力挣钱,而不是如何省钱. 2.再愤怒也不大吼大叫,保持冷静. 3.喜欢的东西自己努力赚钱买. 4.少说多做,能站不坐,适当运动. 5.不要认为找个有钱男人就什么都有了.世界上年轻的女孩子, ...

  2. C++ 读取txt文本内容,并将结果保存到新文本

    循序渐进学习读文件 // readFile.cpp : 定义控制台应用程序的入口点. #include "stdafx.h" #include <iostream> # ...

  3. 【边框】-边框阴影-box-shadow

    CSS3之box-shadow边框阴影 div{box-shadow: 10px 10px 5px #888888;} 来自为知笔记(Wiz)

  4. blade and soul zone overview

    The world of Blade and Soul, is a vast extension of land containing two continents (the Southern Con ...

  5. Excel学习技巧

    ctrl+R 初始化信息 ctrl+T 创建表列 ctrl+o 保存文件

  6. 小游戏Item表

    [Config]1|0|我|1|10|500|0|8|2|4|b5222d10-55a7-4789-8541-8e7430345d54|0|0[Config] [Config]2|1|公主|1|0|5 ...

  7. 160个crackme-之Acid burn.exe

    工具: Ollydbg(OD) 中文版 运行: 我们拿到一个小程序时,总要看看它到底有什么功能,或者说它阻碍了我们什么,也就是寻找突破口! 这就是程序运行后的主界面 我们进入Serial/Name后, ...

  8. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) E. Goods transportation (非官方贪心解法)

    题目链接:http://codeforces.com/contest/724/problem/E 题目大意: 有n个城市,每个城市有pi件商品,最多能出售si件商品,对于任意一队城市i,j,其中i&l ...

  9. gridview的rowdeleting这个函数总是不执行

    今天在做新闻管理时,管理数据的时候需要弹出确认删除的功能,可是此功能总是不能够实现,调试的时候也执行不到该方法,后来方向是忘记给button加上一个属性: 把CommandName设置为delete. ...

  10. RHEL7修改swappiness

    linux系统swappiness参数在内存与交换分区间优化 2014-08-14 10:24:19分类: Linux swappiness的值的大小对如何使用swap分区是有着很大的联系的.swap ...