Android中通过注解代替findViewById方法

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

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

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

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

 

?
1
2
3
4
public @interface TestPerson
{
 
}

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

 

 

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

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

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
//用来标注某个类是用来干嘛的
public @interface ClassFunction
{
   String value() default ;
}
 
//用来标注类中的方法是被谁测试的
public @interface TestPerson
{
   //name是属性而不是方法,gavin是它的默认值,在定义的时候可以不用给定默认值
   String name() default gavin;
}

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

 

 

 

?
1
2
3
4
5
6
7
8
9
10
@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一下

 

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

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@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 ;
}

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

 

 

?
1
2
3
4
5
6
7
8
9
10
11
@ClassFunction (用于描述一个人的基本信息)
public class Person
{
   private static final String TAG = Person;
   
   @TestPerson (name=jj)
   public void setName()
   {
     
   }
}

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

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

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
/**
  * 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类中加入注解

 

 

?
1
2
3
4
5
6
7
8
public class Person {
   private static final String TAG = Person;
   @TestPerson (name=gavin)
   public void getName()
   {
     
   }
}

解析注解

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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) {
     }
   }
}</person>

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

 

 

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

在Activity中加入注解

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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));
         }
       }
     }
   }
 
 
 
}

好了,就写到这里吧,欢迎留言讨论
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值