Support Annotation Library 使用详解

作者: 王世军Steven | 来源:发表于2017-02-17 17:57 被阅读165次

    Support Annotation Library 是提供了一系列元注解,用来帮助开发者在编译期间发现可能存在的BUG.

    1. Nullness 注解

    此类注解包含 :

    • @Nullable 作用于函数参数和返回值,标记参数或者返回值可以为空.
    • @NonNull 作用于函数参数和返回值,标记参数或者返回值不可以为空.

    Android Studio 会自动提示注解错误.

    注解错误

    2. 资源类型注解

    在Android中资源通常用整形值表示,保存在R文件中. 这样存在的问题就是如果一个需要使用Layout资源的地方传入了一个String类型的资源编译期间也不会报错,只有在运行到相应代码时才会发现错误. 使用资源型注解就可以解决这个问题.

    注解符号 标记类型
    @AnimatorRes android.R.animator
    @AnimRes android.R.anim
    @AnyRes 标记整形值是任意一种资源
    @ArrayRes android.R.array
    @AttrRes android.R.attr
    @BoolRes 整形值是布尔类型
    @ColorRes android.R.color
    @Drawable android.R.drawable
    @IdRes android.R.id
    @FracriionRes fraction类型,这种比较少见,这种资源类型常见于Animation XML中.
    @IntegerRes android.R.layout
    @InterpolatorRes android.R.interpolator
    @LayoutRes android.R.layout
    @MenuRes android.R.menu
    @PluralsRes android.R.plurals 表示复数字符串.
    @RawRes android.R.raw
    @StringRes android.R.string
    @StyleableRes android.R.styleable
    @StyleRes android.R.style
    @TransitionRes 标记 transition类型
    @XmlRes android.R.xml

    3. 类型定义注解

    在Android开发中,整数值不仅用来代表资源值,也经常用来代表枚举值. 使用@IntDef 注解可以定义一个新的整形类型的注解.

    用法一 : 定义范围

    // 定义可以接收的常量列表.
    @IntDef({X_1,X_2,X_3})
    // 定义注解.
    public @interface TestMode {}
    // 定义常量
    public final static int X_1 = 0x01;
    public final static int X_2 = 0x02;
    public final static int X_3 = 0x03;
    // 使用定义的注解, 如果mode不是三个常量之一Android Studio会给出警告.
    public void setTestMode(@TestMode int mode){
    
    }
    @TestMode
    public int getTestMode(){
        return X_1;
    }
    // 使用
    public void test(){
        setTestMode(X_1);
    }
    

    用法二 : 定义一个flag标志位,来识别函数参数或者返回值是否符合某一种模式.

    // 定义范围
    @IntDef(flag = true, value = {
            XX_1,XX_2,XX_3
    })
    // 定义注解
    public @interface TestMode2 {}
    // 定义常量
    public static final int XX_1 = 0x01;
    public static final int XX_2 = XX_1 << 1;
    public static final int XX_3 = XX_1 << 2;
    // 使用
    @TestMode2
    public int getMode2(){
        return XX_1;
    }
    public void setMode2(@TestMode2 int mode2){
    
    }
    public void test2(){
        // 这种模式下可以使用多个并在一起
        setMode2(XX_1 | XX_3);
    }
    

    4. 线程注解

    • @UiThread : 标记运行在UI线程.
    • @MainThread : 运行在主线程,一个应用只有一个主线程,主线程也是@UIThread线程,通常情况下我们可以使用@MainThread 来注解生命周期相关的函数,使用@UiThread 来注解视图相关的函数,一般情况下两者可以互换.
    • @WorkerThread : 标记运行在后台线程.
    • @BinderThread : 标记运行在Binder线程中.
    @UiThread
    public void testUiThread(){
        Log.d(TAG,"运行在UI线程中");
    }
    @MainThread
    public void testMainThread(){
        Log.d(TAG, "运行在主线程");
    }
    @WorkerThread
    public void testWorkerThread(){
        Log.d(TAG, "运行在后台线程");
    }
    @BinderThread
    public void testBinderThread(){
        Log.d(TAG, "运行在Binder线程");
    }
    

    5. 值范围注解

    当函数取值是一定范围时,我们可以使用值范围注解来防止调用这传入错误参数.

    • @Size : 对于集合、数组和字符串之类的参数,开使用@Size注解来表示这些参数的大小.

      • @Size(min=1) // 集合币可以为空
      • @Size(max=4) // 字符串最大字符个数是4.
      • @Size(2) // 数组元素两个.
      • @Size(multiple=2) //数组大小是2 的倍数.
    // 数组不能为空
    public void testRange1(@Size(min = 1) final byte[] bbs){
    }
    // 数组长度大4
    public void testRange2(@Size(max = 4) final byte[] bbs){
    }
    // 两个字符
    public void testRange3(@Size(2) String string){
    }
    // 长度是 2 的倍数.
    public void testRange4(@Size(multiple = 2) String string){
    }
    
    • @IntRange : 参数可以是 int 或者 long
    // 0-255
    public void testRange5(@IntRange(from = 0,to = 255) int alpha){
    }
    
    • @FloatRange : 参数是float或者double
    // 0.0-255.0
    public void testRange6(@FloatRange(from = 0.0,to = 255.0) float alpha){
    }
    

    6. 权限注解

    Android 应用在使用某些系统功能时,需要在AndroidManifest.xml中声明权限,否则运行会报错. 使用权限注解@RequiresPermission 可以帮助我们在编译时找出错误.

    • 需要声明一个权限
    // 调用此方法需要声明权限.
    @RequiresPermission(Manifest.permission.SET_WALLPAPER)
    public void testPermissionAnnotation() {
    }
    
    • 需要声明集合中的至少一个权限
    // 调用此方法需要声明下面任何一个权限.
    @RequiresPermission(anyOf = {
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION})
    public void testPermission2(){}
    
    • 需要声明集合中的所有权限
    // 调用此方法需要声明下面所有的权限.
    @RequiresPermission(allOf = {
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION})
    public void testPermission3(){}
    
    • Intent 调用所需权限,可以在Intent的ACTION字符串定义处添加注解
    // Intent 的这个Action需要使用如下权限
    @RequiresPermission(Manifest.permission.EXPAND_STATUS_BAR)
    public static final String ACTION_MY = "custom_action";
    
    • ContentProvider 同时需要读写
    // 对于ContentProvider
    @RequiresPermission.Read(@RequiresPermission(Manifest.permission.READ_CALENDAR))
    @RequiresPermission.Write(@RequiresPermission(Manifest.permission.READ_CALENDAR))
    public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
    

    7. 重写函数注解

    如果API允许重写某个函数,但同时要求重写的函数调用被重写函数则可以使用@CallSuper注解.

    @CallSuper
    public static int testCallSuper() {
        return 0;
    }
    

    8. 返回值注解

    需要调用者对返回值进行某些处理,可以使用@CheckResult 回调. suggest 会是提示内容.

    @CheckResult(suggest = "检查一下返回值呗")
    public static int testReturn(){
        return 12;
    }
    public static void testCheck(){
        int x = testReturn();
    }
    
    返回值注解

    9. 单元测试 @VisibaleForTesting

    使某些变量在单元测试中可见.

    10. @Keep

    用来标记在混淆时不需要混淆的方法.

    参考 : Android 高级进阶

    相关文章

      网友评论

        本文标题:Support Annotation Library 使用详解

        本文链接:https://www.haomeiwen.com/subject/azllwttx.html