Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android Annotation基礎教程

Android Annotation基礎教程

編輯:關於android開發

  Java Annotation

  Java 1.5中開始引入的Annotation,類似於注釋的一種技術,參考了一些網上的譯法,姑且譯成注解吧。

  我們在開發中,用得最多的Annotation莫過於@Override了。大家天天用,可能很多同學卻沒有關注過其背後的細節,我們看一下它的定義:

Java代碼
  1. @Target(ElementType.METHOD)  
  2. @Retention(RetentionPolicy.SOURCE)  
  3. public @interface Override {  
  4. }  

  在Android源碼中,這個注解定義在libcore/luni/src/main/java/java/lang/Override.java中。

  這是一個標稱注解,只在源代碼級有效,主要被編譯器用來判斷是否真的繼承了父類中的方法。

  常用的Annotation還有著名的@Deprecated,過時的建議不用的方法。

  它的定義如下:

Java代碼
  1. @Documented  
  2. @Retention(RetentionPolicy.RUNTIME)  
  3. public @interface Deprecated {  
  4. }  

  另外還有通知編譯器不要做警告的@SuppressWarnings

Java代碼
  1. @Target( { ElementType.TYPE, ElementType.FIELD, ElementType.METHOD,  
  2.         ElementType.PARAMETER, ElementType.CONSTRUCTOR,  
  3.         ElementType.LOCAL_VARIABLE })  
  4. @Retention(RetentionPolicy.SOURCE)  
  5. public @interface SuppressWarnings {  
  6.   
  7.     /** 
  8.      * The list of warnings a compiler should not issue. 
  9.      */  
  10.     public String[] value();  
  11. }  

  元注解

  除了上面幾個常用的注解定義於最基本的java.lang包中,用於實現這幾個Annotation的Annotation都實現在java.lang.annotation包中。它們是被用於實現其它注解所用的。

  元素類型 - ElementType

  就是這個注解可以用於什麼語法單元,比如@Override只能用於方法,方法的類型就是ElementType.METHOD.

  這是一個枚舉,包括下面的類型:

  TYPE: 類,接口,枚舉

  FIELD: 域變量

  METHOD:方法

  PARAMETER:函數參數

  CONSTRUCTOR:構造函數

  LOCAL_VARIABLE:局部變量

  ANNOTATION_TYPE:注解類型

  PACKAGE:包

  @Target

  定義了元素類型,就可以通過這些類型來指定注解適用的類型了。

Java代碼
  1. @Documented  
  2. @Retention(RetentionPolicy.RUNTIME)  
  3. @Target(ElementType.ANNOTATION_TYPE)  
  4. public @interface Target {  
  5.     ElementType[] value();  
  6. }  

  @Target注解就是一個ElementType的數組,就像上面我們看到的用法:

Java代碼
  1. @Target( { ElementType.TYPE, ElementType.FIELD, ElementType.METHOD,  
  2.         ElementType.PARAMETER, ElementType.CONSTRUCTOR,  
  3.         ElementType.LOCAL_VARIABLE })  

  @Documented

Java代碼
  1. @Documented  
  2. @Retention(RetentionPolicy.RUNTIME)  
  3. @Target(ElementType.ANNOTATION_TYPE)  
  4. public @interface Documented {  
  5. }  

  用於描述一個注解是可以生成JavaDoc的,也暗示了這個注解是一個公開的API。

  @Retention

  這是4個元注解中最重要的一個,用於定義這個注解的生命周期。

  取值是另一個枚舉:

  • RetentionPolicy.SOURCE:注解只存在於源代碼中,編譯器生成class代碼時就忽略了

  • RetentionPolicy.CLASS:會編譯進class文件,但是VM執行時調不到

  • RetentionPolicy.RUNTIME:在運行時也可以訪問到

  RetentionPolicy的定義如下:

Java代碼
  1. public enum RetentionPolicy {  
  2.     /** 
  3.      * Annotation is only available in the source code. 
  4.      */  
  5.     SOURCE,  
  6.     /** 
  7.      * Annotation is available in the source code and in the class file, but not 
  8.      * at runtime. This is the default policy. 
  9.      */  
  10.     CLASS,  
  11.     /** 
  12.      * Annotation is available in the source code, the class file and is 
  13.      * available at runtime. 
  14.      */  
  15.     RUNTIME  
  16. }  

  有了這些基礎,再看@Retention的實現,就可以完全看得懂了:

Java代碼
  1. @Documented  
  2. @Retention(RetentionPolicy.RUNTIME)  
  3. @Target(ElementType.ANNOTATION_TYPE)  
  4. public @interface Retention {  
  5.     RetentionPolicy value();  
  6. }  

  @Retention本身是個運行時可用的注解,公開的API,只對注解本身有效。

  它只定義了一個RetentionPolicy枚舉的值。

  通過反射處理注解

  所有的@Target可用的對象都支持用getAnnotations()方法去讀取注解。

  例如,讀取一個類的注解:

Java代碼
  1. Class clazz = ThreadSafeCounter.class;  
  2. Annotation[] as = clazz.getAnnotations();  

  我們通過一個例子來說明:

  首先先定義一個注解,這個注解用於說明這類或者方法是線程安全的,有一個value用於保存鎖對象的名字。

Java代碼
  1. import java.lang.annotation.*;  
  2.   
  3. @Documented  
  4. @Retention(RetentionPolicy.RUNTIME)  
  5. @Target({ElementType.TYPE,ElementType.METHOD})  
  6. public @interface ThreadSafe {  
  7.     String value();  
  8. }  

  下面定義一個使用該注解的類, 類和其中的一個方法都使用這個注解。其實有點廢話,類都線程安全了,方法還能不安全麼,呵呵

Java代碼
  1. import java.lang.annotation.Annotation;  
  2. import java.lang.reflect.Method;  
  3.   
  4. @ThreadSafe("ThreadSafeCounter")  
  5. public class ThreadSafeCounter {  
  6.     private int mCounter;  
  7.   
  8.     public ThreadSafeCounter(int counter) {  
  9.         mCounter = counter;  
  10.     }  
  11.   
  12.     @ThreadSafe("this")  
  13.     public int incAndGet() {  
  14.         synchronized (this) {  
  15.             return mCounter++;  
  16.         }  
  17.     }  

  下面定義一個main方法去通過反射讀注解,先讀類的注解:

Java代碼
  1. public static void main(String[] args){  
  2.     Class clazz = ThreadSafeCounter.class;  
  3.     Annotation[] as = clazz.getAnnotations();  
  4.   
  5.     for(Annotation a:as){  
  6.         ThreadSafe t= (ThreadSafe)a;  
  7.         System.out.println("Annotation type="+clazz.getName());  
  8.         System.out.println("lock name is:"+t.value());  
  9.     }  

  然後再讀取

Java代碼
  1.     Method[] methods = clazz.getMethods();  
  2.     for(Method method: methods){  
  3.         boolean hasAnno = method.isAnnotationPresent(ThreadSafe.class);  
  4.         if(hasAnno){  
  5.             ThreadSafe anno = method.getAnnotation(ThreadSafe.class);  
  6.             System.out.println("method name="+method.getName()+",lock object="+anno.value());  
  7.         }  
  8.     }  
  9. }
  10. }  

  本章內容參考文獻:《Java程序設計完全手冊》,王作啟,伍正雲著,北京:清華大學出版社,2014

  Android中的Annotation

  Android標准的Annotation

  @Nullable

  定義:

Java代碼
  1. @Retention(SOURCE)  
  2. @Target({METHOD, PARAMETER, FIELD})  
  3. public @interface Nullable {  
  4. }  

  源碼級的,可以用於方法、參數和域,表示一個方法或域的值可以合法地為空,或者是函數的返回值可以合法為空。代碼中已經針對為空的情況做了相應的處理。

  這是個標稱注解。

  @NonNull

Java代碼
  1. @Retention(SOURCE)  
  2. @Target({METHOD, PARAMETER, FIELD})  
  3. public @interface NonNull {  
  4. }  

  與@Nullable相反,@NonNull要求一定不能為空。

  @UiThread

  定義:

Java代碼
  1. @Retention(SOURCE)  
  2. @Target({METHOD,CONSTRUCTOR,TYPE})  
  3. public @interface UiThread {  
  4. }  

  表示標有該注解的方法或構造函數應該只在UI線程調用。

  如果注解元素是一個類,說明該類的所有方法都應該在UI線程中調用。

  @MainThread

Java代碼
  1. @Retention(SOURCE)  
  2. @Target({METHOD,CONSTRUCTOR,TYPE})  
  3. public @interface MainThread {  
  4. }  

  這個是要求運行在主線程的

  @WorkerThread

Java代碼
  1. @Retention(SOURCE)  
  2. @Target({METHOD,CONSTRUCTOR,TYPE})  
  3. public @interface WorkerThread {  
  4. }  

  要求運行在工作線程

  @IntRef

  用於定義整數值。

Java代碼
  1. @Retention(CLASS)  
  2. @Target({ANNOTATION_TYPE})  
  3. public @interface IntDef {  
  4.     /** Defines the allowed constants for this element */  
  5.     long[] value() default {};  
  6.   
  7.     /** Defines whether the constants can be used as a flag, or just as an enum (the default) */  
  8.     boolean flag() default false;  
  9. }  

  我們看一個使用@IntRef例子:

Java代碼
  1. @IntDef({HORIZONTAL, VERTICAL})  
  2. @Retention(RetentionPolicy.SOURCE)  
  3. public @interface OrientationMode {}  
  4.   
  5. public static final int HORIZONTAL = 0;  
  6. public static final int VERTICAL = 1;  

  在上面定義的@OrientationMode注釋中,可以支持的值是HORIZONTAL, VERTICAL.

  然後我們再看一個使用flag的例子:

Java代碼
  1. @IntDef(flag = true,  
  2.         value = {  
  3.             SHOW_DIVIDER_NONE,  
  4.             SHOW_DIVIDER_BEGINNING,  
  5.             SHOW_DIVIDER_MIDDLE,  
  6.             SHOW_DIVIDER_END  
  7.         })  
  8. @Retention(RetentionPolicy.SOURCE)  
  9. public @interface DividerMode {}  

  View相關的

  @RemoteView

  支持RemoteView機制,這是一個運行時的注釋.

  定義路徑:/frameworks/base/core/java/android/widget/RemoteViews.java

Java代碼
  1. /** 
  2.  * This annotation indicates that a subclass of View is alllowed to be used 
  3.  * with the {@link RemoteViews} mechanism. 
  4.  */  
  5. @Target({ ElementType.TYPE })  
  6. @Retention(RetentionPolicy.RUNTIME)  
  7. public @interface RemoteView {  
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved