Support Annotation Library是從Android Support Library 19.1 開始引入的一個全新的函數包,它包含一系列有用的元註解,用來幫助開發者在編譯期間發現可能存在的Bug。Support Library自己也使用Annotation Library 提供的註解來完善自身的代碼質量,android Studio 提供可視化的交互以便開發者發現問題。html
Android Support Library 發展到如今已經不止是一個jar包了,而是拆分紅多個獨立的Jar包,例如support-v四、support-v七、gridlayout-v七、design、cardview-v7等等。而Annotation Libary 也是其中之一,默認狀況下是不會包含在工程中的,若是咱們的SDK已經安裝了android Support Repository,那麼咱們打開Project Structure 對話框,並選中一個Module,選中Dependencies選項,點擊「+」按鈕,在彈出的Choose Library Dependency 對話框中輕鬆找到Annotation Library。java
點擊添加後,在Module的build.gradle文件中會新增長Annotation函數庫的依賴以下:android
compile 'com.android.support:support-annotations:26.0.0-alpha1'
此類型包含以下內容:數組
若是在函數參數或返回值使用了上述註解,而又出現違反該註解的代碼時,Android Studio 會給出提示,同時使用Android Lint進行靜態代碼掃描,也會顯示出錯提示。ide
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); test(null); } private void test(@NonNull String str) { Log.e(TAG,str); }
咱們知道,資源是以int整型表示,並保存在R.Java文件中。這就意味着在一個須要Layout資源值函數傳入String字符串,在編譯時不會報錯,只有在運行時纔會報錯,爲了防止這種狀況的出現,可使用資源類型註解。函數
資源類型的註解做用於函數參數、返回值及類的變量,每種資源類型對應一種註解。測試
AnimatorRes:標記整型值是android.R.animation類型。gradle
AnimRes:標記整型是android.R.anim類型。ui
AnyRes:標記整型是任何一種資源類型,若是確切知道表示的是哪個具體資源的話,建議顯式指定。this
ArrayRes:標記整型是android.R.array類型。
AttrRes:標記整型是android.R.attr類型。
BoolRes:標記整型是布爾類型。
ColorRes:標記整型是android.R.color類型。
DrawableRes:標記整型是android.R.drawable類型。
FranctionRes:標記整型值是fraction類型,這個比較少見,這種類型資源常見於Animation
Xml中,好比50%,表示佔parent的50%
IdRes:標記整型是android.R.id類型。
IntegerRes:標記整型是android.R.integer類型。
InterpolatorRes:標記整型是android.R.interpolator類型,插值器,在Animation
Xml中使用較多。
LayoutRes:標記整型是android.R.layout類型。
MenuRes:標記整型是android.R.menu類型。
RawRes:標記整型是android.R.raw類型。
StringRes:標記整型是android.R.string類型。
StyleableRes:標記整型是android.R.styleable類型。
StyleRes:標記整型是android.R.style類型。
XmlRes:標記整型是android.R.xml類型。
看一下例子。這裏傳入字符串如果不加@LayoutRes,是不會報錯,
如果加了就會報錯。提早知道錯誤在哪。這樣就會少不少麻煩。舉個例子,在AppCompatAcitivity的setContentView函數使用@LayoutRes標記它的參數。
@Override public void setContentView(@LayoutRes int layoutResID) { getDelegate().setContentView(layoutResID); }
在Android開發中,整型值不止常常用來表明資源引用值,並且常常用來代替枚舉值。@IntDef註解用來建立一個整型類型定義的新註解,咱們可使用這個新註解來標記本身編譯的API。先看看@IntDef的源碼。
@Retention(SOURCE) @Target({ANNOTATION_TYPE}) public @interface IntDef { /** Defines the allowed constants for this element */ long[] value() default {}; /** Defines whether the constants can be used as a flag, or just as an enum (the default) */ boolean flag() default false; }
public abstract class AnnotationTest { public static final int TEST_1 = 0; public static final int TEST_2 = 1; public static final int TEST_3 = 2; @Retention(RetentionPolicy.SOURCE) @IntDef({TEST_1,TEST_2,TEST_3}) public @interface TestAnnotation{} @TestAnnotation public abstract int getTestAnnotation(); public abstract void setTestAnnotation(@TestAnnotation int testAnnotation); }
使用就很是簡單了,找個類繼承抽象類,實現方法。在調用的時候,只能傳入指定的TEST_1,TEST_2,TEST_3。
這樣就能夠自定義資源類型註解,很是方便。
Android應用開發過程當中,常常會涉及到多種線程的使用,界面相關操做必須在主線程,而耗時操做如文件下載等必須在後臺線程中,
線程註解相關有四種。
@UiThread:標記運行在UI線程,一個應用只有一個UI線程,多數是用於View的標註。(這裏先前有錯誤,感謝樓下評論朋友提醒)
@MainThread:標記運行在主線程,一個應用只有一個主線程,主線程也是@UiThread線程。一般狀況下,咱們使用@MainThread
來註解生命週期相關函數,使用@UiThread來註解視圖相關函數,通常狀況下@MianThread和@UiThraed是能夠互換的。
@WorkerThread:標記運行在後臺運行線程。
@BinderThread:標記運行在Binder線程。
一個典型的例子就是AsyncTask的源碼,咱們截取部分代碼以下。
@MainThread protected void onPreExecute() { } @MainThread protected void onPostExecute(Result result) { } @MainThread protected void onProgressUpdate(Progress... values) { }
在資源類型註解中咱們使用@ColorRes來標記參數類型須要傳入顏色類型的id,而使用@ColorInt註解是標記參數類型須要傳入RGB或者ARGB顏色值的整型值,在TextView的源碼中能夠找到@ColorInt的例子。
@android.view.RemotableViewMethod public void setTextColor(@ColorInt int color) { mTextColor = ColorStateList.valueOf(color); updateTextColors(); }
當函數參數的取值在必定範圍時,可使用註解來防止調用者傳入錯誤的參數,主要註解有三種註解。
@Size:對於相似數組、集合和字符串之類的參數,咱們可使用@Size註解來表示這些參數的大小。用法:
@Size(min=1)//能夠表示集合不能夠爲空
@Size(max=23)//能夠表示字符串最大字符個數爲23
@Size(2)//表示數組元素個數爲2個
@Size(multiple=2)//能夠表示數組大小是2的倍數
@IntRange:參數類型是int或者long,用法以下
public void setAlpha(@IntRange(from=0,to=255) int alpha){...}
public void setAlpha(@FloatRange(from=0.0,to=1.0) float alpha){...}
Android應用在使用某些系統功能時,須要在AndroidManifest,xml中聲明權限,不然在運行時就會提示缺失對應的權限,爲了在編譯時及時發現權限的缺失,咱們可使用@RequiresPermission註解。
@RequiresPermission(Manifest.permission.SET_WALLPAPER) public abstract void setWallpaper(Bitmap bitmap) throws IOException;
@RequiresPermission(anyOf= { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}) public abstract Location getLastKnownLocation(String Provider);
@RequiresPermission(allOf = { Manifest.permission.READ_HISTORY_BOOKMARKS, Manifest.permission.WRITE_HISTORY_BOOKMARKS}) public static final void updateVisitedHistory(ContentResolver cr,String url,boolean real);
@RequiresPermission(android.Manifest.permission.BLUETOOTH) public static final String ACTION_REQUEST_DISCOVERRAVLE = "android.bluetooth.adapter.REQUEST_DISCOVERRAVLE";
@RequiresPermission.Read(@RequestPermission(READ_HISTORY_BOOLMARKS)) @RequiresPermission.Write(@RequestPermission(WRITE_HISTORY_BOOLMARKS)) public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
若是API容許重寫某個函數,可是要求在重寫該函數時須要調用super父類的函數,不然代碼邏輯可能會出錯,那麼能夠加註解@CallSuper來提示開發者。
@CallSuper protected void onCreate(@Nullable Bundle saveInstanceState);
若是咱們編寫的函數須要調用對返回值作某種處理,那麼可使用@CheckResult註解來提示開發者。固然咱們沒有必要對每一個非空返回值的函數都添加這個註解,該註解的主要目的是讓調用者在使用API時不至於懷疑該函數是否會產生反作用。看下Context類中checkPermission中的源碼:
@CheckResult(suggest="#enforcePermission(String,int,int,String)") @PackageManager.PermissionResult public abstract int checkPermission(@NonNull String permission, int pid, int uid); @CheckResult(suggest="#enforceCallingPermission(String,String)") @PackageManager.PermissionResult public abstract int checkCallingPermission(@NonNull String permission);
若是調用者沒有檢查這兩個函數的返回值,那麼就會警告,警告信息中包含suggest屬性中的內容。
單元測試中可能須要訪問到一些不可見的類、函數或者變量,這時可使用@VisibleForTesting註解來使其對測試可見。
@keep是用來標記在Proguard混淆過程當中不須要混淆的類或者方法。在混淆時一些不須要混淆的會使用
-keep class com.foo.bar{public static method>}
public class AnnotationDemo { @Keep public void doSomething(){ // ... } // ... }
java.lang.SuppressWarnings是J2SE 5.0中標準的Annotation之一。能夠標註在類、字段、方法、參數、構造方法,以及局部變量上。做用:告訴編譯器忽略指定的警告,不用在編譯完成後出現警告信息。
注意:SuppressWarnings是java.lang包下的,以前說的都是android.support.annotation包下的
使用:
示例:
@SuppressWarnings(「unchecked」)
告訴編譯器忽略 unchecked 警告信息,如使用List,ArrayList等未進行參數化產生的警告信息。
@SuppressWarnings(「serial」)
若是編譯器出現這樣的警告信息:The serializable class WmailCalendar does not declare a static final serialVersionUID field of type long
使用這個註釋將警告信息去掉。
@SuppressWarnings(「deprecation」)
若是使用了使用@Deprecated註釋的方法,編譯器將出現警告信息。
使用這個註釋將警告信息去掉。
@SuppressWarnings(「unchecked」, 「deprecation」)
告訴編譯器同時忽略unchecked和deprecation的警告信息。
@SuppressWarnings(value={「unchecked」, 「deprecation」})
等同於@SuppressWarnings(「unchecked」, 「deprecation」)
一、抑制單類型警告
@SuppressWarnings("unchecked") public void addItems(String item){ @SuppressWarnings("rawtypes") List items = new ArrayList(); items.add(item); }
二、抑制多類型警告
@SuppressWarnings(value={"unchecked", "rawtypes"}) public void addItems(String item){ List items = new ArrayList(); items.add(item); }
三、抑制所有警告
@SuppressWarnings("all") public void addItems(String item){ List items = new ArrayList(); items.add(item); }
註解目標
經過 @SuppressWarnings 的源碼可知,其註解目標爲類、字段、函數、函數入參、構造函數和函數的局部變量。而家建議註解應聲明在最接近警告發生的位置。
到這裏基本註解都已經說完了,最後說明一下,若是函數庫中使用Annotation Library,並使用Gradle生成aar壓縮包,那麼在編譯時Android Gradle插件會取出這些註解信息並打包在aar文件中,以便函數庫的調用者正常使用咱們的註解信息。aar文件中的annotations.zip文件就是抽取出來的註解信息。
參考:
@SuppressWarnings忽略警告 《Android高級進階》