標籤:
轉自:https://asce1885.gitbooks.io/android-rd-senior-advanced/content/shen_ru_qian_chu_android_support_annotations.html
原文連結:http://anupcowkur.com/posts/a-look-at-android-support-annotations/
在Android Support Library19.1版本中,Android工具小組引入了幾個很酷的註解類型,供開發人員在工程中使用。Support Library自身也使用這些註解,這是一個好兆頭。就讓我們好好研究下。 通過gradle可以很容易的把這些註解添加到我們的工程中:
compile ‘com.android.support:support-annotations:20.0.0‘
有三種類型的註解可供我們使用:
Nullness註解;
資源類型註解;
IntDef和StringDef註解;
我們將通過代碼例子來講解每一種類型的作用以及在工程中如何使用它們。
Nullness註解
使用@NonNull註解修飾的參數不能為null。在下面的代碼例子中,我們有一個取值為null的name變數,它被作為參數傳遞給sayHello函數,而該函數要求這個參數是非null的String類型:
public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String name = null; sayHello(name); } void sayHello(@NonNull String s) { Toast.makeText(this, "Hello " + s, Toast.LENGTH_LONG).show(); }}
由於代碼中參數String s使用@NonNull註解修飾,因此IDE將會以警告的形式提醒我們這個地方有問題:
如果我們給name賦值,例如String name = “Our Lord Duarte”,那麼警告將消失。使用@Nullable註解修飾的函數參數或者傳回值可以為null。假設User類有一個名為name的變數,使用User.getName()訪問,那麼我們可以編寫如下代碼:
public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); User user = new User("Our Lord Duarte"); Toast.makeText(this, "Hello " + getName(user), Toast.LENGTH_LONG).show(); } @Nullable String getName(@NonNull User user) { return user.getName(); }}
因為getName函數的傳回值使用@Nullable修飾,所以調用:
Toast.makeText(this, "Hello " + getName(user), Toast.LENGTH_LONG).show();
沒有檢查getName的傳回值是否為空白,將可能導致crash。
資源類型註解
是否曾經傳遞了錯誤的資源整型值給函數,還能夠愉快的得到本來想要的整型值嗎?資源類型註解可以協助我們準確實現這一點。在下面的代碼中,我們的sayHello函數預期接受一個字串類型的id,並使用@StringRes註解修飾:
public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sayHello(R.style.AppTheme); } void sayHello(@StringRes int id) { Toast.makeText(this, "Hello " + getString(id), Toast.LENGTH_LONG).show(); }}
而我們傳遞了一個樣式資源id給它,這時IDE將提示警告如下:
類似的,我們把警告的地方使用一個字串資源id代替警告就消失了:
sayHello(R.string.name);
IntDef和StringDef註解
我們要介紹的最後一種類型的註解是基於Intellij的“魔術常量”檢查機制(http://blog.jetbrains.com/idea/2012/02/new-magic-constant-inspection/) (我們不需要詳細瞭解這個機制具體是如何?的,想瞭解的話可以點選連結)。
很多時候,我們使用整型常量代替枚舉類型(效能考慮),例如我們有一個IceCreamFlavourManager類,它具有三種模式的操作:VANILLA,CHOCOLATE和STRAWBERRY。我們可以定義一個名為@Flavour的新註解,並使用@IntDef指定它可以接受的實值型別。
public class IceCreamFlavourManager { private int flavour; public static final int VANILLA = 0; public static final int CHOCOLATE = 1; public static final int STRAWBERRY = 2; @IntDef({VANILLA, CHOCOLATE, STRAWBERRY}) public @interface Flavour { } @Flavour public int getFlavour() { return flavour; } public void setFlavour(@Flavour int flavour) { this.flavour = flavour; }}
這時如果我們使用錯誤的整型值調用IceCreamFlavourManager.setFlavour時,IDE將報錯如下:
IDE甚至會提示我們可以使用的有效取值:
我們也可以指定整型值作為標誌位,也就是說這些整型值可以使用’|’或者’&’進行與或等操作。如果我們把@Flavour定義為如下標誌位:
@IntDef(flag = true, value = {VANILLA, CHOCOLATE, STRAWBERRY}) public @interface Flavour { }
那麼可以如下調用:
iceCreamFlavourManager.setFlavour(IceCreamFlavourManager.VANILLA & IceCreamFlavourManager.CHOCOLATE);
@StringDef用法和@IntDef基本差不多,只不過是針對String類型而已。
關於將來計劃增加哪些新的註解類型或者這些註解的依賴以及和Intellij自身的註解如何互動等等問題,可以查看網址:http://tools.android.com/tech-docs/support-annotations。
A Look At Android Support Annotations