標籤:div 檢查 鼓勵 png draw append article 問題 anim
尊重他人的勞動成果,轉載請標明出處:http://blog.csdn.net/gengqiquan/article/details/70185731, 本文出自:【gengqiquan的部落格】
上篇部落格嘀咕了註解的基本知識。這篇和大家嘮嘮Android提供的一些編譯限制註解以及怎麼自訂貼合自己項目架構的限制註解
Android支援Java預設的那些註解,同時通過一些依賴庫也額外提供了很多註解,瞭解並熟練使用這些註解能夠讓你的代碼更加嚴謹,結構更加清晰、架構更易維護
Android support library從19.1版本開始引入了一個新的註解庫Support Annotations
support appcompa-v7裡面預設包含了這個庫,如果你沒有使用的話也可以通過添加單獨依賴的方式引入
在model的build.gradle中添加如下配置:
dependencies { compile ‘com.android.support:support-annotations:25.2.0‘}
選取的25.2.0版本的,包含了如下幾種類型的註解
資源引用限制類:用於限制參數必須為對應的資源類型
AnimRes AnyRes ArrayRes AttrRes BoolRes ColorRes DimenRes DrawableRes FractionRes IdRes IntegerRes InterpolatorRes LayoutRes MenuRes PluralsRes Px RawRes StringRes StyleableRes StyleRes TransitionRes XmlRes
線程執行限制類:用於限制方法或者類必須在指定的線程執行
AnyThread BinderThread MainThread UiThread WorkerThread
參數為空白性限制類:用於限制參數是否可以為空白
NonNull Nullable
類型範圍限制類:用於限制標註值的值範圍
FloatRang IntRange
類型定義類:用於限制定義的註解的取值集合
IntDef StringDef
其他的功能性註解:
CallSuper CheckResult ColorInt Dimension Keep Px RequiresApi RequiresPermission RestrictTo Size VisibleForTesting
下面分別舉例怎麼使用
資源引用限制類
用於當我們期望的輸入為所註解對應的類型時,可以加上對應的資源類型註解。這樣如果輸入了非預期類型的資源ID就編譯器就會報錯,比如我們在寫項目架構時定義了一個設定主布局的抽象方法,需要子類繼承該類是實現這個方法,返回一個layout布局ID,一般我們會這麼寫
public abstract int getLayoutID();
這樣這是限制了返回的資料類型必須為int。如果實現該類的人穿了一個drawable的ID或者一個int數值,也是可以正常編譯的。要等到運行到該介面時才會報錯。這個時候我們就可以用Support Annotations包提供的註解來標註該方法
@LayoutRes public abstract int getLayoutID();
這樣當實現該類的人傳入一個非layout的ID時編譯器就會報except resource of type layout異常 而導致無法編譯 。
線程執行限制類
在我們編碼的時候,合理的抽取代碼為獨立的方法是一個很好的習慣,不僅有利於代碼的閱讀以及相同邏輯的多處調用,也方便後期的重構,同時抽取代碼的時候能夠讓你思考這塊邏輯實現是否合理是否過於臃腫。但抽取出來的方法我們有可能放在編寫的activity裡也可能放在公用類或者變成靜態方法,這個時候你不能保證知道調用者會在哪裡使用你這段代碼。
除非他花時間去仔細閱讀你的代碼,否則他也不會知道他調用的方法裡調用了多少方法,比如方法裡包含了一些io操作的代碼,或者方法執行特別耗時應該在子線程調用。或者方法裡面操作了UI必須在主線程調用。這個時候就可以用線程執行限制類註解在你的方法上,當個調用者並沒有再你期望的線程中調用這個方法時編譯器就會報錯。
需要注意的是這些註解的範圍是類和方法。標註與某個類時表明該類以及內部的所以方法都必須在指定線程調用執行,包括構造方法。
比如MVP中view的介面方法
public interface IBaseView { @UiThread void showLoading(); }
載入框必須要在UI線程調用
參數為空白性限制類
這個就比較簡單了,大家在實現Android的SDK方法的時候經常可以在重寫系統方法的時候遇到
NonNull 標註在參數上時編譯器會檢查參數欄位是否可能為空白,標記在方法上時會檢查返回的值是否為空白。可能為空白的情況編譯器會提示你有一個潛在的崩潰危險
Nullable 標註在參數或有傳回值的方法上,表明該參數或方法傳回值可以為空白
類型限制類
限制參數的資料類型
FloatRange 限定被註解對象必須為float或者double
@Retention(CLASS)@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE})public @interface FloatRange { //起始值 double from() default Double.NEGATIVE_INFINITY; //終點值 double to() default Double.POSITIVE_INFINITY; //是否包含起始值 boolean fromInclusive() default true; //是否包含終點值 boolean toInclusive() default true;}
IntRange 限定被註解對象必須為int或者long
@Retention(CLASS)@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE})public @interface IntRange { //起始值,包含起始值 long from() default Long.MIN_VALUE; //終點值,包含終點值 long to() default Long.MAX_VALUE;}
類型定義類
一般用於替代枚舉,當我們定義API時,有時候需要傳入本地定義好的一些值。為了使這些值具有可讀性我們會選擇用靜態常量,有時候需要限制參數的可取集合。而這些值得類型可能是基礎資料類型。為了避免調用API的人傳入了其他的不可處理的非預期值進來,我們往往會選擇用枚舉。而枚舉是比較耗費效能的。這個時候我們就可以用註解來替代
比如我們有一個圖片上傳的API。上傳類型需要選擇jpg還是png,枚舉的方式就是比較簡單了。直接定義一個圖片類型枚舉
public enum ImgType { jpg,png;}
API
public void uploadImg(ImgType type) {}
你現在我們用註解的方式來實現這個需求
我們先定義兩個int常量,放入一個常量類Data裡
public class Data { public static final int JPG=1000; public static final int PNG=1001;}
然後我們定義一個ImgType註解
@IntDef({Data.JPG,Data.PNG})@Retention(RetentionPolicy.SOURCE)public @interface ImgType {}
這樣我們就定義了一個編譯時間檢查的註解,我們把這個註解打在上傳圖片的API的型別參數上
public void uploadImg(@ImgType int type) {}
這樣當我們調用API時,一旦我們傳入的參數不是Data.JPG或者Data.PNG,編譯器就會報錯無法通過編譯
StringDef用法類似
其他功能類
CallSuper 如果你的API允許使用者重寫你的方法,但是你又需要你自己的方法(父方法)在重寫的時候也被調用,這時候你可以使用@CallSuper註解
CheckResult 如果你的方法返回一個值,你期望調用者用這個值做些事情,那麼你可以使用@CheckResult註解標註這個方法,一般用於那些傳回值被使用才有意義的API
ColorInt 當你期望傳遞的是一個真實的RGB或者ARGB的顏色值而不是顏色資源ID的時候可以使用該註解來提示API調用者
Dimension 標註的對象或者方法必須提供一個int的值,就是Android的螢幕上描述距離的一種單位
Keep 啟用混淆的時候告訴編譯器被註解的對象不要混淆
Px 標註的對象或者方法必須提供一個int的值,pixel
RequiresApi 當你提供的API是基於某個SDK版本開發的,要求調用者必須處理好低SDK版本相容操作的時候,或者告訴調用者你的API只能在某個版本的SDK之後才可以正常的工作
RequiresPermission 告訴調用你API的人你的API需要特定的許可權
如果你至少需要許可權集合中的一個,你可以使用anyOf屬性
@RequiresPermission(anyOf = { Manifest.permission.INTERNET, Manifest.permission.READ_PHONE_STATE})public abstract string getSaveUser();
如果你同時需要多個許可權,你可以用allOf屬性
@RequiresPermission(allOf = { Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_PHONE_STATE})public abstract string getSaveUser();
RestrictTo 註解的對象只接受一個特定範圍的值,值範圍是一個枚舉
Size 限制一個列表集合的大小
@Retention(CLASS)@Target({PARAMETER,LOCAL_VARIABLE,METHOD,FIELD,ANNOTATION_TYPE})public @interface Size { //該註解必須要給一個值,預設-1 long value() default -1; //最小的大小 long min() default Long.MIN_VALUE; // 最大的大小 long max() default Long.MAX_VALUE; //大小必須為這個值的倍數,預設為1 long multiple() default 1;}
VisibleForTesting 這個註解作用的對象測試的時候可以直接調用
以上就是Support Annotations提供的註解的用法了,由於篇幅問題,下一篇我們在聊怎麼定義以及代碼解析運行時註解
有什麼建議的可以留言喔
如果我的部落格對您有協助,請留言鼓勵下或者點個贊吧!
我建了一個QQ群(群號:121606151),用於大家討論交流Android技術問題,有興趣的可以加下,大家一起進步。
Android提供的常用註解以及自訂註解代替枚舉