安卓註解使用介紹

在Java中,註解(Annotation)引入始於Java5,用來描述Java代碼的元信息,一般狀況下註解不會直接影響代碼的執行,儘管有些註解能夠用來作到影響代碼執行。html

在代碼文件中使用‘@’字符告訴編譯器接下來的是一個註解。註解能夠用在類,構造方法,成員變量,方法,參數等的聲明中。做用主要是對編譯器警告等輔助工具產生影響,若是傳遞了錯誤的類型那麼編譯器就會發出警告,這樣就能夠在編碼和維護的過程當中輔助發現問題,提升開發效率,提高代碼質量,也促進造成編碼規範。java

安卓開發中用到的註解主要有四個方面:JDK內置註解、JDK自定義註解包、android sdk內置註解、android.support.annotation註解。android

JDK內置註解

以下圖,左側是JDK提供的三個標準註解,在java.lang包內。右側JDK提供的四個是對自定義註解的支持,在java.lang.annotation包內。數組

@Deprecated是一個標記註解,表示被標記的成員變量或者成員方法已經不建議使用,緣由多是這個方法/變量有缺陷或者在新的SDK中已經不被支持。app

@Override註解在繼承過程當中,標識對父類方法的覆蓋關係。這個在Java中不是必須的,可是建議在須要的地方強制使用。防止在子類或者父類中誤操做修改方法簽名或者遺漏相關的代碼(kotlin中對於子類覆蓋父類方法強制使用override關鍵字,再也不須要註解標記)。ide

@SuppressWarnings用來抑制編譯器生成警告信息,對指定類型的警告保持靜默。能夠修飾類、方法、方法參數、屬性和局部變量,採用就近原則,儘可能放在被須要靜默的警告語句附近。接收一個字符串或者一個字符集做爲參數(參數詳細介紹參考文章),它指示將取消的警告。工具

JDK提供了四種元註解,支持用戶對註解進行自定義擴展。自定義註解後面會詳細介紹,這裏先略過。gradle

Android SDK內置註解

Android SDK註解有兩個@SuppressLint和@TargetApi。ui

這兩個註解是使用Lint靜態檢測對應的標記。若是禁用了Lint,用或者不用這些註解都沒有太大關係。

@TargetApi:Android工程須要設置所支持的最小的系統版本,Android Studio是在Gradle中設置minSdkVersion的值。若是某個方法或者類被聲明須要在某個版本和更高版本的系統上運行,可使用@RequiresApi(requires)聲明支持的最小系統版本。當在聲明minSdkVersion的工程中使用了requires大於minSdkVersion的類或者方法時,Lint就會報錯誤提醒,這時候可使用@TargetApi使Lint保持靜默,可是要添加代碼爲低版本的系統提供對應的備選方案,不然在低版本系統上運行會產生崩潰。google

@SuppressLint:上面的@TargetApi註解只針對API版本進行註解,使Lint對版本錯誤保持靜默。@SuppressLint針對的範圍更廣,經過設置一個參數(identified by the lint issue id)通知Lint對相應的警告⚠和錯誤❎️保持靜默。

@SuppressLint("NewApi"),這個註解能夠實現@TargetApi(version)相同的做用,只是沒有指定特定的API版本,致使工程師和Lint都不知道響應的範圍,容易致使錯誤,不建議使用。

android support註解

Android Support Library提供com.android.support:support-annotations對Android的註解進行了拓展。下圖以v25爲例列出了全部定義的46個註解(到v27增長了5個,分別爲ColorLong、FontRes、GuardedBy、HalfFloat、NavigationRes)。

  • 其中22個資源類註解,以下:
  • 取值範圍類3個註解,IntRange/FloatRange對響應類型的變量或參數規定取值範圍,參數有from和to兩個;Size對數組的長度約束,參數min/max(含)組合聲明數組的長度範圍,參數value指定數據的具體長度,參數multiple指定數組長度必須是某個數字的倍數。
  • Android中新引入的替代枚舉的註解有IntDef和StringDef,他們惟一的區別一個是int類型,一個是string類型,下面咱們列一下官方API文檔中給出的使用方法。

枚舉類型的註解的使用,先定義一系列可用的取值,而後定義一個註解使用@IntDef或者@StringDef指定新的註解可用的取值列表。

使用 Enum 的缺點:每個枚舉值都是一個對象,在使用它時會增長額外的內存消耗,因此枚舉相比於Integer和String會佔用更多的內存,較多的使用 Enum 會增長 DEX 文件的大小,會形成運行時更多的開銷,使咱們的應用須要更多的空間。特別是分dex的大APP,枚舉的初始化很容易致使ANR。

@Retention(SOURCE)
@StringDef({
    POWER_SERVICE,
    WINDOW_SERVICE,
    LAYOUT_INFLATER_SERVICE
})
public @interface ServiceName {}
public static final String POWER_SERVICE = "power";
public static final String WINDOW_SERVICE = "window";
public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
複製代碼
@Retention(SOURCE)
@IntDef({
    NAVIGATION_MODE_STANDARD, 
    NAVIGATION_MODE_LIST, 
    NAVIGATION_MODE_TABS
})
public @interface NavigationMode {}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
  ...
public abstract void setNavigationMode(@NavigationMode int mode);
@NavigationMode
public abstract int getNavigationMode();
複製代碼

自定義註解

上面的枚舉註解,就是自定義註解的例子。自定義註解使用關鍵字@interface聲明,而後用相應的屬性修飾。

@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Entity {
    String value();
    String name();
}
複製代碼
  • @Documented表示擁有該註解的元素可經過javadoc此類的工具進行文檔化。該類型應用於註解那些影響客戶使用帶註釋(comment)的元素聲明的類型。若是類型聲明是用Documented來註解的,這種類型的註解被做爲被標註的程序成員的公共API。
  • @Inherited:表示該註解類型被自動繼承
  • @Retention:表示該註解類型的註解保留的時長。可用的參數都在枚舉類型RetentionPolicy中給出了定義。當註解類型聲明中沒有@Retention元註解,則默認保留策略爲RetentionPolicy.CLASS。
  • @Target:表示該註解類型的所使用的程序元素類型。可用的參數都在枚舉類型ElementType中給出了定義。當註解類型聲明中沒有@Target元註解,則默認爲可適用全部的程序元素。

附錄:ButterKnife

使用ButterKnife只須要在module的gradle文件中加入下面代碼:

implementation 'com.jakewharton:butterknife:8.4.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
複製代碼

在library工程中,直接使用R.xxx.xxx會報「元素值必須爲常量表達式」的錯誤提示,處理步驟以下:

  • 在根gradle文件中添加(版本根據須要變化):
classpath 'com.jakewharton:butterknife-gradle-plugin:8.4.0'
複製代碼
  • 在module的gradle中添加:
apply plugin: 'com.jakewharton.butterknife'
複製代碼
  • R.xxx.xxx替換成R2.xxx.xxx

參考文章

相關文章
相關標籤/搜索