Android如何使用註解進行代碼檢查

原文首發於微信公衆號:jzman-blog,歡迎關注交流!

Android Studio 內置了代碼檢查工具 Lint,可在菜單欄選擇 Analyze > Inspect Code 執行相應的代碼檢查,代碼檢查能夠根據推斷一些不合法的潛在問題,有助於在開發階段發現開發者因爲主管原因導致的一下代碼問題,Android 官方提供了註解庫 support-annotations 來幫助開發者及早發現問題,下面是常用的一些註解,主要內容如下:

  1. Nullness註解
  2. 資源註解
  3. 線程註解
  4. 值約束註解
  5. 權限註解
  6. 返回值註解
  7. CallSuper註解
  8. Typedef註解
  9. 可訪問性註解

Nullness註解

使用 Nullness 註解可以檢查給定變量、參數和返回值是否允許 null 值,具體如下:

  • @Nullable :表示可以爲 null 的變量、參數或返回值,
  • @NonNull :表示不可爲 null 的變量、參數或返回值。
@NonNull
@Override
public View onCreateView(String name, @NonNull Context context,@NonNull AttributeSet attrs) {
    //...
}

資源註解

資源註解的使用可使得在源碼階段讓編輯器檢查書寫的不規範,也可在一定程度上優化代碼結構,下面是常見的資源註解如下:

  • @StringRes: 表示檢查是否包含R.string引用
  • @ColorRes: 表示檢查是否包含R.color引用
  • @ColorInt: 表示檢查是否包含表示顏色的整型
  • @DrawableRes: 表示檢查是否包含R.drawable引用
  • @DimenRes: 表示檢查是否包含R.dimen引用
  • @InterpolatorRes:表示檢查是否包含插值器引用

線程註解

線程註解可以檢查某個方法是否從某個特定類型的線程中調用,支持一下線程註解,具體如下:

  • @MainThread:表示主線程
  • @UiThread:表示 UI 線程
  • @WorkerThread:表示工作線程
  • @BinderThread:表示Binder線程
  • @AnyThread:表示任何一個線程

上述註解中 @MainThread@UiThread 在大多時候表示的都是同一線程,如果應用中帶有多個試圖,UI 線程可與主線程不同,故可使用 @UIThread 標註與應用的視圖層次相關聯的方法,使用 @MainThread 僅標註與應用生命週期相關聯的方法。線程註解最常用的一個用途是 AsyncTask 使用中的方法替換,因爲 AsyncTask 會執行後臺操作並將結果發佈到 UI 線程。

值約束註解

使用值約束註解可驗證傳遞的參數的值的合法性,可以藉此指定參數的設置範圍,可在一定程度上減少代碼在主觀程度上出現的錯誤,常見的值約束註解如下:

  • @IntRange:表示可以驗證整型參數是否在指定範圍內
  • @FloatRange:表示可以驗證浮點型參數是否在指定範圍內
  • @Size:表示可以驗證集合、數組、字符串參數是否在指定範圍內,可指定最大值、最小值以及確切值

上面的註解有一些可使用的參數,如 from、to、min 等,使用時具體在某個註解體重查看定義即可。

權限註解

權限註解 @RequiresPermission 可以驗證方法調用方的權限,即當使用了權限註解的方法時會檢查有沒有指定的權限,如果沒有則會提示要在 AndroidManifest.xml 文件中申明權限,如果是危險權限還有進行權限動態申請,使用方式參考如下:

/**
 * 單個權限檢查
 * @param message
 */
@RequiresPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
public void setMessage(String message) {
}

/**
 * 全部權限檢查
 * @param message
 */
@RequiresPermission(allOf = {
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.READ_EXTERNAL_STORAGE})
public void setMesage(String message) {
}

/**
 * 某個權限檢查
 * @param message
 */
@RequiresPermission(anyOf = {
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.READ_EXTERNAL_STORAGE})
public void setMesage(String message) {
}

返回值註解

返回值註解 @CheckResult 會檢查某個方法的返回值是否被使用,如果沒有被使用,則會根據 suggest 配置建議使用相同公民沒有返回值的另一個方法,如果返回值使用了,則和未加該註解的方法一樣,使用方式參考如下:

@CheckResult(suggest="#enforcePermission(String,int,int,String)")
public  int checkPermission(@NonNull String permission, int pid, int uid){
    return 0;
}

如果沒有使用返回值提示如下:
jzman-blog
當返回值沒有被使用,則會建議使用相同功能沒有返回值的另一個方法,簡而言之,返回值註解 @CheckResult 能夠表示某個方法實際使用的時方法本身的處理還是方法最終的處理結果。

CallSuper註解

使用 @CallSuper 註解會驗證子類的重寫方法是否調用父類的實現,這樣約束的好處是可保證父類的實現不會修改,當然,如果不使用該註解,子類重寫父類的方法可以不調用弗父類的默認實現,具體參考如下:

/**
 * 父類
 * @CallSuper註解的使用
 */
public class Test {
    //使用@CallSuper註解,子類重寫該方法時必須調用該方法
    @CallSuper
    protected void onCreate(){
        
    }
}

下面是 Test 類的實現類:

/**
 * 子類
 * @CallSuper註解的使用
 */
public class TestImpl extends Test{
    @Override
    protected void onCreate() {
        super.onCreate();
        /**
         * 如果不調用父類的方法,則會提示
         * Some methods, such as View#onDetachedFromWindow, require that you also call the super implementation as part of your method.
         */
    }
}

Typedef註解

使用 @IntDef@StringDef 註解 可以創建整型和字符串的枚舉註解來驗證其他代碼中使用的某些整型和字符串,可以保證代碼中的某些常量整型或常量字符串是某些具體定義的常量集,這兩個註解的位置只能是註解。

開發中總會使用到枚舉,枚舉在一定程度上可使得代碼結構更清晰,但枚舉的使用會增加內存的開銷,這裏可以用 Typedef 註解的方式來代替枚舉,下面是 Tyoedef 註解的使用,參考如下:

/**
 * Typedef 註解的定義
 */
public class ActionType {

    public static final int ACTION_TYPE_0 = 0;
    public static final int ACTION_TYPE_1 = 1;
    public static final int ACTION_TYPE_2 = 2;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({ACTION_TYPE_0,ACTION_TYPE_1,ACTION_TYPE_2})
    public @interface ActionTypeDef{

    }
}

下面是上述 Typedef 註解的使用方式,參考如下:

/**
 * Typedef註解的使用
 * @param value
 */
private void setValue(@ActionType.ActionTypeDef int value) {
    switch (value) {
        case ActionType.ACTION_TYPE_0:
            break;
        case ActionType.ACTION_TYPE_1:
            break;
        case ActionType.ACTION_TYPE_2:
            break;

//        case 100://不能使用未定義的整型
//            break;
    }
}

可見 Typedef 註解約束了使用到的某些整型,當然還可以是字符串,這樣也能達到枚舉的作用。

可訪問性註解

可訪問性註解是 @VisibleForTesting@Keep 可以表示方法、字段、類的可訪問性。具體如下:

  • @VisibleForTesting:表示註解的某個代碼塊的可見性高於能夠測試時需要的水平
  • @Keep:表示被註解的代碼塊將不會被混淆。

最常用的可能就是資源註解,如 @StringRes、@ColorRes、@ColorInt等,還有Typeof 註解,該註解可以在替換枚舉在 Android 開發中帶來的性能影響,如果平時留意這些註解在 Android 源碼中也經常使用,所以可在開發過程中嘗試去使用這些註解以進行必要的代碼檢查。

可以關注公衆號:零點小築(jzman-blog),一起交流學習。
jzman-blog

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章