深入淺出Android Support Annotations

原文鏈接:http://anupcowkur.com/posts/a-look-at-android-support-annotations/
在Android Support Library19.1版本中,Android工具小組引入了幾個很酷的注解類型,供開發(fā)者在工程中使用。Support Library自身也使用這些注解,這是一個好兆頭。就讓我們好好研究下。 通過gradle可以很容易的把這些注解添加到我們的工程中:

compile 'com.android.support:support-annotations:20.0.0'

有三種類型的注解可供我們使用:

  • Nullness注解;

  • 資源類型注解;

  • IntDef和StringDef注解;

我們將通過代碼例子來講解每一種類型的作用以及在工程中如何使用它們。

Nullness注解

使用@NonNull注解修飾的參數(shù)不能為null。在下面的代碼例子中,我們有一個取值為null的name變量,它被作為參數(shù)傳遞給sayHello函數(shù),而該函數(shù)要求這個參數(shù)是非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();
    }

}

由于代碼中參數(shù)String s使用@NonNull注解修飾,因此IDE將會以警告的形式提醒我們這個地方有問題:



如果我們給name賦值,例如String name = “Our Lord Duarte”,那么警告將消失。使用@Nullable注解修飾的函數(shù)參數(shù)或者返回值可以為null。假設(shè)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函數(shù)的返回值使用@Nullable修飾,所以調(diào)用:
Toast.makeText(this, "Hello " + getName(user), Toast.LENGTH_LONG).show();

沒有檢查getName的返回值是否為空,將可能導(dǎo)致crash。

資源類型注解

是否曾經(jīng)傳遞了錯誤的資源整型值給函數(shù),還能夠愉快的得到本來想要的整型值嗎?資源類型注解可以幫助我們準(zhǔn)確實現(xiàn)這一點。在下面的代碼中,我們的sayHello函數(shù)預(yù)期接受一個字符串類型的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的“魔術(shù)常量”檢查機(jī)制(http://blog.jetbrains.com/idea/2012/02/new-magic-constant-inspection/) (我們不需要詳細(xì)了解這個機(jī)制具體是如何實現(xiàn)的,想了解的話可以點擊鏈接)。
很多時候,我們使用整型常量代替枚舉類型(性能考慮),例如我們有一個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;
    }

}

這時如果我們使用錯誤的整型值調(diào)用IceCreamFlavourManager.setFlavour時,IDE將報錯如下:



IDE甚至?xí)崾疚覀兛梢允褂玫挠行У娜≈担?/p>


我們也可以指定整型值作為標(biāo)志位,也就是說這些整型值可以使用’|’或者’&’進(jìn)行與或等操作。如果我們把@Flavour定義為如下標(biāo)志位:
@IntDef(flag = true, value = {VANILLA, CHOCOLATE, STRAWBERRY})
    public @interface Flavour {
    }

那么可以如下調(diào)用:

iceCreamFlavourManager.setFlavour(IceCreamFlavourManager.VANILLA & IceCreamFlavourManager
                .CHOCOLATE);

@StringDef用法和@IntDef基本差不多,只不過是針對String類型而已。
關(guān)于將來計劃增加哪些新的注解類型或者這些注解的依賴以及和Intellij自身的注解如何交互等等問題,可以查看網(wǎng)址:http://tools.android.com/tech-docs/support-annotations。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容