@interface 在Android开发中的使用
引子:java用 @interface Annotation{ } 定义一个注解 @Annotation,一个注解是一个类。
在使用
360
桌面一键清理内存,或者点击手机
HOME
键前后台切换时,是有可能将
Android
手机的一些权值较低的
ACTIVITY“kill”
。
但这种
KILL
不是真的
KILL,Android OS
会把
activity
的内容清掉(可以理解为
context
)
,
然后在下次起动这个
activity
(长按
home
键进入)时,根据上次
"KILL"
时候,系统保存的一些
activity
引用信息,重新启动一个全新的
activity,
所以会重新调用
onCreate
()方法。
而onCreate()方法中一般默认有一句,“
super.onCreate(savedInstanceState);
”
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
如果是正常的A,B两个activity进行startActivity()进行切换时,
savedInstanceState这变量实际是nulL,的所以一种比较优雅的做法是。在项目中将所有的Activity继承于一个统一的BaseActivity,然后在BaseActivity中@override
onSaveInstanceState(){}方法,通过注解@Annotation去
在真正的业务Activity中去把需要用到的全局,和本Activity中的可能被非正常变量进行声明。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface SaveWithActivity {
}
根据google的activity的生命周期文档,实际发生作用的效果是:在activity将被OS清理之前(这里的清理,系统会保存当前activity的一些堆栈信息,用于下回重启activity),系统会调用
protected void onSaveInstanceState(Bundle outState) {} 我们就在这里去通过反射把所有的filds[]去输出的outState,下次启动时,在Oncreate()中判断 protected void onCreate(Bundle savedInstanceState) {},
savedInstanceState是不是空,如果是空说明是正常的Activity跳转,如果不空说明是异常关闭activity后,ANDROID OS 重新启动的一个“新activity”,此时调用在BaseActivity()中写好的一个loadData()
以下摘自:
java用
@interface Annotation{ }
定义一个注解 @Annotation,一个注解是一个类。
@Override,@Deprecated,@SuppressWarnings
为常见的3个注解。
注解相当于一种标记,在程序中加上了注解就等于为程序加上了某种标记,以后,
JAVAC
编译器,开发工具和其他程序可以用反射来了解你的类以及各种元素上有无任何标记,看你有什么标记,就去干相应的事。
注解
@Override
用在方法上,当我们想重写一个方法时,在方法上加
@Override
,当我们方法的名字出错时,编译器就会报错,如图:
注解
@Deprecated
,用来表示某个类的属性或方法已经过时,不想别人再用时,在属性和方法
上用
@Deprecated
修饰,如图:
注解
@SuppressWarnings
用来压制程序中出来的警告,比如在没有用泛型或是方法已经过时的时候,如图:
注解
@Retention
可以用来修饰注解,是注解的注解,称为元注解。
Retention注解有一个属性value,是RetentionPolicy类型的,Enum RetentionPolicy是一个枚举类型,这个枚举决定了Retention注解应该如何去保持,也可理解为Rentention 搭配 RententionPolicy使用。RetentionPolicy有3个值:
CLASS
RUNTIME
SOURCE
用@Retention(RetentionPolicy.CLASS)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,但不会被虚拟机读取在运行的时候;
用
@Retention(RetentionPolicy.SOURCE )
修饰的注解
,
表示注解的信息会被编译器抛弃,不会留在
class
文件中,注解的信息只会留在源文件中;
用
@Retention(RetentionPolicy.RUNTIME )
修饰的注解,表示注解的信息被保留在
class
文件
(
字节码文件
)
中当程序编译时,会被虚拟机保留在运行时,
所以他们可以用反射的方式读取。RetentionPolicy.RUNTIME 可以让你从JVM中读取Annotation注解的信息,以便在分析程序的时候使用.
1.package com.self;
2.import java.lang.annotation.Retention;
3.import java.lang.annotation.RetentionPolicy;
4.
5.@Retention(RetentionPolicy.RUNTIME)
6.public @interface MyTarget
7.{ }
8.定义个一注解@MyTarget,用RetentionPolicy.RUNTIME修饰;
9.package com.self;
10.import java.lang.reflect.Method;
11.public class MyTargetTest
12.{
13. @MyTarget
14. public void doSomething()
15. {
16. System.out.println("hello world");
17. }
18.
19. public static void main(String[] args) throws Exception
20. {
21. Method method = MyTargetTest.class.getMethod("doSomething",null);
22. if(method.isAnnotationPresent(MyTarget.class))//如果doSomething方法上存在注解@MyTarget,则为true
23. {
24. System.out.println(method.getAnnotation(MyTarget.class));
25. }
26. }
27.}
28.上面程序打印:@com.self.MyTarget(),如果RetentionPolicy值不为RUNTIME,则不打印。
29.
30. @Retention(RetentionPolicy.SOURCE )
31.public @interface Override
32.
33.@Retention(RetentionPolicy.SOURCE )
34.public @interface SuppressWarnings
35.
36.@Retention(RetentionPolicy.RUNTIME )
37.public @interface Deprecated
38.由上可以看出,只有注解@Deprecated在运行时可以被JVM读取到
39.
40.注解中可以定义属性,看例子:
41.@Retention(RetentionPolicy.RUNTIME)
42.public @interface MyAnnotation
43.{
44. String hello() default "gege";
45. String world();
46. int[] array() default { 2, 4, 5, 6 };
47. EnumTest.TrafficLamp lamp() ;
48. TestAnnotation lannotation() default @TestAnnotation(value = "ddd");
49. Class style() default String.class;
50.}
51.上面程序中,定义一个注解@MyAnnotation,定义了6个属性,他们的名字为:
52.hello,world,array,lamp,lannotation,style.
53.属性hello类型为String,默认值为gege
54.属性world类型为String,没有默认值
55.属性array类型为数组,默认值为2,4,5,6
56.属性lamp类型为一个枚举,没有默认值
57.属性lannotation类型为注解,默认值为@TestAnnotation,注解里的属性是注解
58.属性style类型为Class,默认值为String类型的Class类型
59.
60.看下面例子:定义了一个MyTest类,用注解@MyAnnotation修饰,注解@MyAnnotation定义的属性都赋了值
61.@MyAnnotation(hello = "beijing", world="shanghai",array={},lamp=TrafficLamp.RED,style=int.class)
62.public class MyTest
63.{
64. @MyAnnotation(lannotation=@TestAnnotation(value="baby"), world = "shanghai",array={1,2,3},lamp=TrafficLamp.YELLOW)
65. @Deprecated
66. @SuppressWarnings("")
67. public void output()
68. {
69. System.out.println("output something!");
70. }
71.}
72. 接着通过反射读取注解的信息:
73.public class MyReflection
74.{
75. public static void main(String[] args) throws Exception
76. {
77. MyTest myTest = new MyTest();
78. Class c = MyTest.class;
79. Method method = c.getMethod("output", new Class[] {});
80. //如果MyTest类名上有注解@MyAnnotation修饰,则为true
81. if(MyTest.class.isAnnotationPresent(MyAnnotation.class))
82. {
83. System.out.println("have annotation");
84. }
85. if (method.isAnnotationPresent(MyAnnotation.class))
86. {
87. method.invoke(myTest, null); //调用output方法
88. //获取方法上注解@MyAnnotation的信息
89. MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
90. String hello = myAnnotation.hello();
91. String world = myAnnotation.world();
92. System.out.println(hello + ", " + world);//打印属性hello和world的值
93. System.out.println(myAnnotation.array().length);//打印属性array数组的长度
94. System.out.println(myAnnotation.lannotation().value()); //打印属性lannotation的值
95. System.out.println(myAnnotation.style());
96. }
97. //得到output方法上的所有注解,当然是被RetentionPolicy.RUNTIME修饰的
98. Annotation[] annotations = method.getAnnotations();
99. for (Annotation annotation : annotations)
100. {
101. System.out.println(annotation.annotationType().getName());
102. }
103. }
104.}
105.上面程序打印:
106.have annotation
107.output something!
108.gege, shanghai
109.3
110.baby
111.class java.lang.String
112.com.heima.annotation.MyAnnotation
113.java.lang.Deprecated
114.
115.如果注解中有一个属性名字叫value,则在应用时可以省略属性名字不写。
116.可见,@Retention(RetentionPolicy.RUNTIME )注解中,RetentionPolicy.RUNTIME是注解属性值,属性名字是value,
117.属性的返回类型是RetentionPolicy,如下:
118.public @interface MyTarget
119.{
120. String value();
121.}
122.可以这样用:
123. @MyTarget("aaa")
124. public void doSomething()
125. {
126. System.out.println("hello world");
127. }
128.
129.注解@Target也是用来修饰注解的元注解,它有一个属性ElementType也是枚举类型,
130.值为:ANNOTATION_TYPE CONSTRUCTOR FIELD LOCAL_VARIABLE METHOD PACKAGE PARAMETER TYPE
131.如@Target(ElementType.METHOD) 修饰的注解表示该注解只能用来修饰在方法上。
132.@Target(ElementType.METHOD)
133.@Retention(RetentionPolicy.RUNTIME)
134.public @interface MyTarget
135.{
136. String value() default "hahaha";
137.}
138.如把@MyTarget修饰在类上,则程序报错,如:
139.@MyTarget
140.public class MyTargetTest
注解大都用在开发框架中吧,好了有关注解就学习那么多了,谢谢。