Android之Support Annotation Library元注解

注意:本篇文章是本人阅读相关文章所写下的总结,方便以后查阅,所有内容非原创,侵权删。

本篇文章内容来自于
Android高级进阶 顾浩鑫
Android开发小技巧@IntDef(译 )
Android进阶系列之Support Annotation Library使用详解

目录

  1. 什么是Support Annotation Library
  2. 如何添加Support Annotation Library
  3. 注解分类介绍
    --3.1 Nullness注解 @Nullable @NonNull
    --3.2 资源类型注解 @xxxRes
    --3.3 类型定义注解 @IntDef
    --3.4 线程注解 @UiThread等
    --3.5 RGB颜色值注解 @ColorInt
    --3.6 值范围注解 @Size @IntRange @FloatRange
    --3.7 权限注解 @RequiresPermission
    --3.8 重写函数注解 @CallSuper
    --3.9 返回值注解 @CheckResult
    --3.10 使不可见类对测试可见 @VisibleForTesting
    --3.11 标记不需要混淆的类或者方法@Keep
  4. 注意点
    --4.1 当使用Gradle生成arr压缩包

1. 什么是Support Annotation Library

Support Annotation Library是从Android Support Library 19.1开始引入的一个全新的函数包,它包含一系列有用的元注解,用来帮助开发者在编译期间发现可能存在的bug,Support Library本身也使用Annotation Library 提供的注解来完善自身的代码质量,Android Studio 提供可视化的交互以便开发者发现问题。

这些注解的生命周期为源码时期,也就是在编译之后则不再保留,通常用于辅助代码上的静态检查。
当出现违反注解的代码时,Android Studio 会给出提示,同时使用Android Lint进行静态代码扫描,也会显示出错提示。

Android Support Library 22.2中,新增了13种新的Annotation Library注解。因此,在实际开发中我们应该尽量使用最新版本的函数包,以便能够使用更多的元注解来提高代码质量。

2.如何添加Support Annotation Library

默认情况下Support Annotation Library是不包含在工程中的。

第一步:打开Tools-Android-SDK Manger,查看SDK是否已经安装了Android Support Repository

第二步:如果我们的SDK已经安装了Android Support Repository,
那么我们打开Project Structure 对话框,并选中一个Module,选中Dependencies选项,点击“+”按钮,在弹出的Choose Library Dependency 对话框中轻松找到Annotation Library。


3. 注解分类介绍

3.1 Nullness注解

@Nullable 作用于函数参数或返回值,标记参数或返回值为可以空。
@NonNull 作用于函数参数或返回值,标记参数或返回值为不能为空。

使用实例

public void test(@NonNull String str)

3.2 资源类型注解

为什么要使用资源类型注解?
我们知道,资源是以int整型表示,并保存在R.java文件中。这就意味着在一个需要Layout资源值函数传入String字符串,在编译时不会报错,只有在运行时才会报错,为了防止这种情况的出现,可以使用资源类型注解。

资源类型的注解作用于函数参数、返回值及类的变量,每种资源类型对应一种注解。

AnimatorRes:标记整型值是android.R.animator类型。
AnimRes:标记整型是android.R.anim类型。
AnyRes:标记整型是任何一种资源类型,如果确切知道表示的是哪一个具体资源的话,建议显式指定。
ArrayRes:标记整型是android.R.array类型。
AttrRes:标记整型是android.R.attr类型。
BoolRes:标记整型是布尔类型。
ColorRes:标记整型是android.R.color类型。
DrawableRes:标记整型是android.R.drawable类型。
FranctionRes:标记整型值是fraction类型,这个比较少见,这种类型资源常见于Animation Xml中,比如50%,表示占parent的50%
IdRes:标记整型是android.R.id类型。
IntegerRes:标记整型是android.R.integer类型。
InterpolatorRes:标记整型是android.R.interpolator类型,插值器,在Animation Xml中使用较多。
LayoutRes:标记整型是android.R.layout类型。
MenuRes:标记整型是android.R.menu类型。
Plurals:标记整型是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类型。

使用实例

    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        getDelegate().setContentView(layoutResID);
    }

3.3 类型定义注解

在Android开发中,整型值不止经常用来代表资源引用值,而且经常用来代替枚举值。
由于Enum通常需要两倍以上的存储空间,因此应当尽量避免Enum的使用。
则可以用

该注解用来创建一个整型类型定义的新注解,我们可以使用这个新注解来标记自己编译的API。

@IntDef //该注解用来创建一个整型类型定义的新注解,我们可以使用这个新注解来标记自己编译的API。

使用实例
使用可参考Android开发小技巧@IntDef(译 )
使用一:正常使用

//定义
@Retention(RetentionPolicy.SOURCE)
@IntDef({NavigationMode.ONE, NavigationMode.TWO, NavigationMode.THREE, NavigationMode.FOUR})
public @interface NavigationMode {
    int ONE = 1;
    int TWO = 2;
    int THREE = 3;
    int FOUR = 4;
}

//使用
    @NavigationMode
    public int haha(){
        return NavigationMode.ONE;
    }


很妙的应用:有一大堆常量,又经常要对他们做switch判断



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

//定义
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true,value = {NavigationMode.ONE, NavigationMode.TWO, NavigationMode.THREE, NavigationMode.FOUR})
public @interface NavigationMode {
    int ONE = 1;
    int TWO = 2;
    int THREE = 3;
    int FOUR = 4;
}
//使用
    public int find(@NavigationMode int dex) {
        return -1;
    }
    find(NavigationMode.ONE | NavigationMode.THREE);

3.4 线程注解

Android应用开发过程中,经常会涉及到多种线程的使用,界面相关操作必须在主线程,而耗时操作如文件下载等必须在后台线程中。
该注解是不能切换线程的,只是起到一个提示作用。

1.@UiThread:标记运行在UI线程,一个应用只有一个UI线程,多数是用于View的标注。
2.@MainThread:标记运行在主线程,一个应用只有一个主线程,主线程也是@UiThread线程。
通常情况下,我们使用@MainThread来注解生命周期相关函数,使用@UiThread来注解视图相关函数,一般情况下@MianThread和@UiThraed是可以互换的。
3.@WorkerThread:标记运行在后台运行线程。
4.@BinderThread:标记运行在Binder线程。

使用

    @MainThread
    protected void onPostExecute(Result result) {
    }

3.5 RGB颜色值注解

在资源类型注解中我们使用@ColorRes来标记参数类型需要传入颜色类型的id,
使用@ColorInt注解是标记参数类型需要传入RGB或者ARGB颜色值的整型值。

@ColorInt

使用

//在TextView的setTextColor的方法中
    public void setTextColor(@ColorInt int color) {
        mTextColor = ColorStateList.valueOf(color);
        updateTextColors();
    }

//使用
tvShow.setTextColor(getResources().getColor(R.color.colorAccent));
tvShow.setTextColor(Color.argb(127, 255, 0, 255));

3.6 值范围注解

当函数参数的取值在一定范围时,可以使用注解来防止调用者传入错误的参数,

1.@Size:对于类似数组、集合和字符串之类的参数,我们可以使用@Size注解来表示这些参数的大小。
用法:
@Size(min=1)//可以表示集合不可以为空
@Size(max=23)//可以表示字符串最大字符个数为23
@Size(2)//表示数组元素个数为2个
@Size(multiple=2)//可以表示数组大小是2的倍数

2.@IntRange:参数类型是int或者long,
用法如下
public void setAlpha(@intRange(from=0,to=255) int alpha){...}

3.@FloatRange:参数类型是float或者double,用法如下。
public void setAlpha(@FloatRange(from=0.0,to=1.0) float alpha){...}

3.7 权限注解

Android应用在使用某些系统功能时,需要在AndroidManifest,xml中声明权限,否则在运行时就会提示缺失对应的权限,
为了在编译时及时发现权限的缺失,我们可以使用@RequiresPermission注解。

使用

1.如果需要一个权限则加注解。
@RequiresPermission(Manifest.permission.SET_WALLPAPER)

2.如果需要一个集合至少一个权限,那么就加注解。
@RequiresPermission(anyOf= {Manifest.permission.SET_WALLPAPER,Manifest.permission.CAMERA})

3.如果同时需要多个权限,那么就加注解。
@RequiresPermission(allOf ={Manifest.permission.SET_WALLPAPER,Manifest.permission.CAMERA})

4.对于Intent调用所需权限的ACTION字符串定义处添加注解。
@RequiresPermission(android.Manifest.permission.BLUETOOTH)
String ACTION_REQUEST_DISCOVERRAVLE = "android.bluetooth.adapter.REQUEST_DISCOVERRAVLE";

5.对于ContentProvider所需权限,可能有读和写两个操作。对应不同的权限。
@RequiresPermission.Read(@RequestPermission(READ_HISTORY_BOOLMARKS))
@RequiresPermission.Write(@RequestPermission(WRITE_HISTORY_BOOLMARKS))
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks);

3.8 重写函数注解

如果API允许重写某个函数,但是要求在重写该函数时需要调用super父类的函数。可以加注解@CallSuper来提示开发者。

使用

定义父类的时候:
    @CallSuper
    protected void onCreate(@Nullable Bundle savedInstanceState) {...}
定义子类的时候:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); //没有这句话会报错
    }

3.9 返回值注解

如果我们编写的函数需要调用者对返回值做某些处理,那么可以使用@CheckResult注解来提示开发者。

    @CheckResult(suggest="#enforcePermission(String,int,int,String)")
    @PackageManager.PermissionResult
    public abstract int checkPermission(@NonNull String permission, int pid, int uid);

3.10 @VisibleForTesting

单元测试中可能需要访问一些不可见的类、函数或者变量,这时可以使用@VisibleForTesting注解来使其对测试可见。

3.11 @Keep

@keep是用来标记在Proguard混淆过程中不需要混淆的类或者方法
在混淆时一些不需要混淆的会使用
-keep class com.foo.bar{public static <method>}
有了@Keep之后,就可以在编码时标注出一些不需要混淆的类或者方法。

使用

public class utils {
  @Keep
  public void doSomething(){...} //该方法不会被混淆
}

4.注意点

4.1 当使用Gradle生成arr压缩包

如果函数库中使用Annotation Library,并使用Gradle生成arr压缩包。
那么在编译时Android Gradle插件会抽取出这些注解信息并打包在arr文件中,以便函数库的调用者正常使用我们的注解信息。

arr文件中的annotation.zip文件就是抽取出来的注解信息。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容