Android Support Library
從
19.1
版本開始引入了一個新的注解庫,其中包含了很多的元注解,使用它們修飾我們的代碼, 可以讓我們提高程序的開發(fā)效率,讓我們更早的發(fā)現(xiàn)問題。以及對代碼施以規(guī)范,讓代碼更加有可讀性。本文和大家
簡單介紹了
下這些注解,以及其使用,一起來看看吧,希望對大家
學(xué)習(xí)android有所幫助。
注:現(xiàn)在我們新建項目直接就依賴了 support.appcompat
包,其中已經(jīng)依賴了
annotations
包。如果你的項目中寫如下注解報錯,可以添加注解包:
dependencies {
compile 'com.android.support:support-annotations:22.2.0'
}
@IntDef & @StringDef
替代 Java
中枚舉的注解,以
@IntDef
為例,定義和使用如下:
@IntDef({RED, BLUE, YELLOW})
@Retention(RetentionPolicy.SOURCE)
public @interface LightColors{};
public
static
final
int RED = 1;
public
static
final
int BLUE = 2;
public
static
final
int YELLOW = 3;
public
void
setColor(@LightColors
int color){
}
· @interface
:聲明新的枚舉注解類型。
· @Retention(RetentionPolicy.SOURCE)
:告知編譯器不將枚舉的注解數(shù)據(jù)存儲在
.class
文件中。
如果允許常量與標(biāo)志(例如:|
、
&
和
^
等等)相結(jié)合,則我們可以使用
flag
屬性,如:
@IntDef(flag = true,
value = {RED, BLUE, YELLOW})
使用:
setColor(
RED | BLUE);
@Nullable & @NonNull
· @Nullable
:注解的元素可以為
null
。
· @NonNull
:注解的元素不可以為
null
。
上面的注解可以修飾如下元素:
1
,方法參數(shù)。如:
@Nullable
private String
data;
2
,方法的返回值。 如:
@Nullable
public String getData(){
return
data;
}
3
,成員屬性。如:
public
void
setData(@Nullable String data){
}
當(dāng)用空的參數(shù)傳給被 @NonNull
修飾的方法參數(shù)的方法時,會給出如下警告提示(編譯不會報錯):
passing "null"
argument
to parameter annotated
as @NotNull
@FloatRange & @IntRange
@FloatRange
和
@IntRange
是用于限定范圍的注解。其中
@FloatRange
是限定
float
類型的,而
@IntRange
是限定
int
類型的。它們同上注解一樣,可以修飾方法參數(shù)、方法返回值、成員屬性。
以 @IntRange
為例,修飾方法參數(shù)的定義如下:
public
void
setAge(@IntRange(from = 1, to = 180) int age){
}
如果調(diào)用該方法傳的參數(shù)不在 1 - 180
的范圍內(nèi), 如:
setAge(0)
,那么編譯會直接報如下錯:
value must
be ≥ 1 and ≤ 180 (was 0)
@Size
@Size
注解的作用是限定長度的,同上注解一樣,可以修飾方法參數(shù)、方法返回值、成員屬性。
·
限定字符串的長度:
public
void
setData(@Size(4) String data){
}
當(dāng)傳入的字符串長度不等于 4
時,編譯器會直接報錯:
Length must be exactly 4
·
限定數(shù)組的長度:
public
void
setData(@Size(4) int[] data){
}
特殊的限定,如限定為 2
的倍數(shù):
public
void
setData(@Size(multiple = 2) int[] data){
}
·
限定最小的長度:
@Size(min = 2)
·
限定最大的長度:
@Size(max = 2)
等同于
@Size(2)
寫法:
@Size(value = 2)
@RequiresPermission
該注解作用是表明方法所執(zhí)行的內(nèi)容需要權(quán)限。如需要單個權(quán)限:
@
RequiresPermission(
Manifest.
permission.
CALL_PHONE)
private void callPhone(String phone){
}
需要一組權(quán)限:
@RequiresPermission(allOf = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE})
public
static
final
void copyFile(String dest, String source) {
...
}
對于 intent
權(quán)限,我們可以定義在
intent
操作名稱的字符串上:
@
RequiresPermission(
android.
Manifest.
permission.
BLUETOOTH)
public static final String ACTION_REQUEST_DISCOVERABLE =
"android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
對于需要單獨讀寫權(quán)限的內(nèi)容提供程序的權(quán)限,我們可以在 @RequiresPermission.Read
或
@RequiresPermission.Write
注解中包含每個權(quán)限要求:
@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
如果權(quán)限依賴于提供給方法參數(shù)的特定值,那么可以對參數(shù)本身使用 @RequiresPermission
而不用列出具體的權(quán)限,如
startActivity(intent)
方法:
public
abstract
void
startActivity(@RequiresPermission Intent intent, @Nullable Bundle) {...}
當(dāng)我們使用這種方式(間接權(quán)限)時,構(gòu)建工具將執(zhí)行數(shù)據(jù)流分析以檢查傳遞到方法的參數(shù)是否具有任何@RequiresPermission
注解。如:
Intent intent =
new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:1234567890"));
startActivity(intent);
這里的 startActivity(intent)
就直接報錯了:
call requires permission which may be rejected
by
user: code should explicitly
check
to see
if permission
isavailable (
with `checkPermission`)
or explicitly handle a potential `SecurityException`
因為 Intent.ACTION_CALL
中標(biāo)記了權(quán)限注解:
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)@RequiresPermission(Manifest.permission.CALL_PHONE)
public static final String ACTION_CALL = "android.intent.action.CALL";
@CheckResult
@CheckResult
注解是作用于方法上的,作用是檢驗有沒有處理返回值。如果沒有處理返回值則會報錯。
@CheckResult
public String getData(String
data) {
return
data.trim();
}
線程注解
線程注解可以檢查某個方法是否從特定類型的線程調(diào)用。支持以下線程注解:
·@MainThread
:表示標(biāo)記的方法只應(yīng)在主線程調(diào)用。如果標(biāo)記的是一個類,那么該類中的所有方法都應(yīng)該是在主線程被調(diào)用。例:(通常,應(yīng)用程序的主線程也是
Ui
線程。但是,在特殊情況下,應(yīng)用程序的主線程可能不是其
Ui
線程)
@MainThread
public
void
deliverResult(D data) { ... }
·@UiThread
:表示標(biāo)記的方法或構(gòu)造函數(shù)只應(yīng)該在
Ui
線程上調(diào)用。如果標(biāo)記的是一個類,那么該類中的所有方法都應(yīng)是在
Ui
線程被調(diào)用。例:
@UiThread
public abstract void setText(@NonNull String text) {...}
·@WorkerThread
:表示標(biāo)記的方法只應(yīng)該在工作線程上調(diào)用。如果標(biāo)記的是一個類,那么該類中的所有方法都應(yīng)是在一個工作線程上調(diào)用。例:
@WorkerThread
protected
abstract FilterResults
performFiltering(CharSequence constraint);
·@BinderThread
:表示標(biāo)記的方法只應(yīng)在綁定線程上調(diào)用。如果標(biāo)記的是一個類,那么該類中的所有方法都應(yīng)是在綁定線程被調(diào)用。例:
@BinderThread
public BeamShareData
createBeamShareData() { ... }
·@AnyThread
:表示可以從任何線程調(diào)用帶標(biāo)記的方法。如果標(biāo)記的是一個類,那么該類中的所有方法都可以從任何線程中調(diào)用。例:
@AnyThread
public
void
deliverResult(D data) { ... }
構(gòu)建工具會將 @MainThread
和
@UiThread
注解視為可以互換,因此,我們可以從
@MainThread
方法調(diào)用
@UiThread
方法,反之亦然。不過如果系統(tǒng)應(yīng)用在不同線程上帶有多個試圖,
Ui
線程可與主線程不同。因此,我們應(yīng)該使用
@UiThread
標(biāo)注于應(yīng)用的視圖層次結(jié)構(gòu)關(guān)聯(lián)的方法,使用
@MainThread
僅標(biāo)注于應(yīng)用生命周期關(guān)聯(lián)的方法。
資源注解
在 Android
中幾乎所有的資源都有其對于的
id
,我們在使用的時候可以直接通過
id
來,如:
textView.setText(
getResources().getText(
R.string.app_name));
但是這樣如果沒有寫指定的資源注解的話就會風(fēng)險,比如隨便傳了個 0
,那么就會找不到對應(yīng)的資源。
為了避免由于自己的粗心大意而引發(fā)的錯誤,我們就可以使用資源注解了,如:
public
int
getText(@StringRes int id){
}
這樣當(dāng)我們調(diào)用該方法時,如果傳遞的參數(shù)并不是 String
類型的資源
id
,那么編譯器就會報錯提示。
除了
@StringRes
資源注解外,還有:
· @IntegerRes
:
R.integer
類型資源。
· @AnimatorRes
:
R.animator
類型資源。
· @AnimRes
:
R.anim
類型資源。
· @ArrayRes
:
R.array
類型資源。
· @AttrRes
:
R.attr
類型資源。
· @BoolRes
:
R.bool
類型資源。
· @ColorRes
:
R.color
類型資源。
· @DimenRes
:
R.dimen
類型資源。
· @DrawableRes
:
R.drawable
類型資源。
· @FractionRes
:
R.fraction
類型資源。(百分比)
· @IdRes
:
R.id
類型資源。
· @InterpolatorRes
:
R.interpolator
類型資源。(插值器)
· @LayoutRes
:
R.layout
類型資源。
· @MenuRes
:
R.menu
類型資源。
· @PluralsRes
:
R.plurals
類型資源。(復(fù)數(shù))
· @RawRes
:
R.raw
類型資源。
· @StyleableRes
:
R.styleable
類型資源。
· @StyleRes
:
R.style
類型資源。
· @TransitionRes
:
R.transition
類型資源。
· @XmlRes
:
R.xml
類型資源。
· @AnyRes
:未知資源。(表示自己不知道是什么類型的資源。比如有可能為
R.drawable
也有可能是
R.string
。)
@ColorInt
@ColorInt
注解的作用為:限定顏色值。(
ARGB
:
0xAARRGGBB
)
public
void
setColor(@ColorInt int color) {
}
如果直接使用資源 id
,則會報錯,如下:
setColor(R.color.colorAccent)//
報錯
正確的使用是:
setColor(0xFFFF00FF);
如果要使用資源 id
,則可以通過
ContextCompat.getColor()
方法來:
setColor(
ContextCompat.getColor(
context, R.color.colorAccent));
@CallSuper
該注解用于修飾方法,表示重寫該方法時必須調(diào)用 super
方法。如
onCreate()
方法:
@CallSuper
protected
void
onCreate(Bundle savedInstanceState) {
}
重寫 onCreate()
方法時,必須調(diào)用
super
方法:
super.onCreate(savedInstanceState);
否則報錯。
@VisibleForTesting & @Keep
使用 @VisibleForTesting
和
@Keep
注解可以表示方法、類、或字段的可訪問性。
· @VisibleForTesting
: 標(biāo)記的指定代碼在測試時是否可見。
· @Keep
:標(biāo)記的指定代碼在混淆時不會被混淆。
來源:
稀土掘金