文档章节

Android进阶Support Annotation Library 使用详解

KingBoxing123
 KingBoxing123
发布于 2017/09/04 09:52
字数 2811
阅读 16
收藏 0
点赞 0
评论 0

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

Android Support Library 发展到现在已经不止是一个jar包了,而是拆分成多个独立的Jar包,例如support-v4、support-v7、gridlayout-v7、design、cardview-v7等等。而Annotation Libary 也是其中之一,默认情况下是不会包含在工程中的,如果我们的SDK已经安装了android Support Repository,那么我们打开Project Structure 对话框,并选中一个Module,选中Dependencies选项,点击“+”按钮,在弹出的Choose Library Dependency 对话框中轻松找到Annotation Library。

这里写图片描述

点击添加后,在Module的build.gradle文件中会新增加Annotation函数库的依赖如下:

compile 'com.android.support:support-annotations:26.0.0-alpha1'
  • 下面我们按照类型进行一一介绍。

1. Nullness 注解

此类型包含如下内容:

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

如果在函数参数或返回值使用了上述注解,而又出现违反该注解的代码时,Android Studio 会给出提示,同时使用Android Lint进行静态代码扫描,也会显示出错提示。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        test(null);
    }
    private void test(@NonNull String str) {
        Log.e(TAG,str);
    }
  • 我们用Android Lint扫描这个文件的话,在扫描结果中会出现如下错误:

这里写图片描述

2. 资源类型注解

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

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

  • AnimatorRes:标记整型值是android.R.animation类型。

  • 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类型。

  • RawRes:标记整型是android.R.raw类型。

  • StringRes:标记整型是android.R.string类型。

  • StyleableRes:标记整型是android.R.styleable类型。

  • StyleRes:标记整型是android.R.style类型。

  • XmlRes:标记整型是android.R.xml类型。

看一下例子。这里传入字符串若是不加@LayoutRes,是不会报错,

若是加了就会报错。提前知道错误在哪。这样就会少很多麻烦。举个例子,在AppCompatAcitivity的setContentView函数使用@LayoutRes标记它的参数。

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

3. 类型定义注解

在Android开发中,整型值不止经常用来代表资源引用值,而且经常用来代替枚举值。@IntDef注解用来创建一个整型类型定义的新注解,我们可以使用这个新注解来标记自己编译的API。先看看@IntDef的源码。

@Retention(SOURCE)  
@Target({ANNOTATION_TYPE})  
public @interface IntDef {  
    /** Defines the allowed constants for this element */  
    long[] value() default {};  

    /** Defines whether the constants can be used as a flag, or just as an enum (the default) */  
    boolean flag() default false;  
}
  • 这里面可以定义一个布尔值,还可以定义多个long类型的值。那么就以long数组举例。
public abstract class AnnotationTest {  
    public static final int TEST_1 = 0;  
    public static final int TEST_2 = 1;  
    public static final int TEST_3 = 2;  
    @Retention(RetentionPolicy.SOURCE)  
    @IntDef({TEST_1,TEST_2,TEST_3})  
    public @interface TestAnnotation{}  

    @TestAnnotation  
    public abstract int getTestAnnotation();  

    public abstract void setTestAnnotation(@TestAnnotation int testAnnotation);  
}
  • 这里给TestAnnotation注解加上了@IntDef,这样在使用TestAnnotation的时候必须传入指定参数,若是非法在编译时就会报异常。

使用就非常简单了,找个类继承抽象类,实现方法。在调用的时候,只能传入指定的TEST_1,TEST_2,TEST_3。

这样就可以自定义资源类型注解,非常方便。

4. 线程注解

Android应用开发过程中,经常会涉及到多种线程的使用,界面相关操作必须在主线程,而耗时操作如文件下载等必须在后台线程中,

线程注解相关有四种。

  • @UiThread:标记运行在UI线程,一个应用只有一个UI线程,多数是用于View的标注。(这里先前有错误,感谢楼下评论朋友提醒)

  • @MainThread:标记运行在主线程,一个应用只有一个主线程,主线程也是@UiThread线程。通常情况下,我们使用@MainThread

来注解生命周期相关函数,使用@UiThread来注解视图相关函数,一般情况下@MianThread和@UiThraed是可以互换的。

  • @WorkerThread:标记运行在后台运行线程。

  • @BinderThread:标记运行在Binder线程。

一个典型的例子就是AsyncTask的源码,我们截取部分代码如下。

    @MainThread
    protected void onPreExecute() {
    }
    @MainThread
    protected void onPostExecute(Result result) {
    }
    @MainThread
    protected void onProgressUpdate(Progress... values) {
    }
  •  

5. RGB颜色值注解

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

@android.view.RemotableViewMethod
public void setTextColor(@ColorInt int color) {
        mTextColor = ColorStateList.valueOf(color);
        updateTextColors();
    }
  •  

6. 值范围注解

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

  • @Size:对于类似数组、集合和字符串之类的参数,我们可以使用@Size注解来表示这些参数的大小。用法:

    • @Size(min=1)//可以表示集合不可以为空

    • @Size(max=23)//可以表示字符串最大字符个数为23

    • @Size(2)//表示数组元素个数为2个

    • @Size(multiple=2)//可以表示数组大小是2的倍数

  • @IntRange:参数类型是int或者long,用法如下

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

7. 权限注解

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

  • 如果函数调用需要声明一个权限,语句如下:
@RequiresPermission(Manifest.permission.SET_WALLPAPER)
public abstract void setWallpaper(Bitmap bitmap) throws IOException;
  • 如果需要一个集合至少一个权限,语句如下:
@RequiresPermission(anyOf= {
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION})
public abstract Location getLastKnownLocation(String Provider);
  • 如果同时需要多个权限,语句如下。
@RequiresPermission(allOf = {
Manifest.permission.READ_HISTORY_BOOKMARKS,
Manifest.permission.WRITE_HISTORY_BOOKMARKS})
public static final void updateVisitedHistory(ContentResolver cr,String url,boolean real);
  • 对于Intent调用所需权限,可以在Intent的ACTION字符串定义处添加注解。语句如下:
@RequiresPermission(android.Manifest.permission.BLUETOOTH)
public static final String ACTION_REQUEST_DISCOVERRAVLE = "android.bluetooth.adapter.REQUEST_DISCOVERRAVLE";
  • 对于ContentProvider所需权限,可能有读和写两个操作。对应不同的权限。
@RequiresPermission.Read(@RequestPermission(READ_HISTORY_BOOLMARKS))
@RequiresPermission.Write(@RequestPermission(WRITE_HISTORY_BOOLMARKS))
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
  •  

8. 重写函数注解

如果API允许重写某个函数,但是要求在重写该函数时需要调用super父类的函数,否则代码逻辑可能会出错,那么可以加注解@CallSuper来提示开发者。

@CallSuper
protected void onCreate(@Nullable Bundle saveInstanceState);
  •  

9. 返回值注解

如果我们编写的函数需要调用对返回值做某种处理,那么可以使用@CheckResult注解来提示开发者。当然我们没有必要对每个非空返回值的函数都添加这个注解,该注解的主要目的是让调用者在使用API时不至于怀疑该函数是否会产生副作用。看下Context类中checkPermission中的源码:

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

    @CheckResult(suggest="#enforceCallingPermission(String,String)")
    @PackageManager.PermissionResult
    public abstract int checkCallingPermission(@NonNull String permission);
  •  

如果调用者没有检查这两个函数的返回值,那么就会警告,警告信息中包含suggest属性中的内容。

10. @VisibleForTesting注解

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

11. @Keep注解

@keep是用来标记在Proguard混淆过程中不需要混淆的类或者方法。在混淆时一些不需要混淆的会使用

-keep class com.foo.bar{public static method>}
  • 有了@Keep之后,就可以在编码时标注出一些不需要混淆的类或者方法
public class AnnotationDemo {
    @Keep
    public void doSomething(){
    // ...
    }
// ...
}
  •  

12. @SuppressWarnings忽略警告

java.lang.SuppressWarnings是J2SE 5.0中标准的Annotation之一。可以标注在类、字段、方法、参数、构造方法,以及局部变量上。作用:告诉编译器忽略指定的警告,不用在编译完成后出现警告信息。

注意:SuppressWarnings是java.lang包下的,之前说的都是android.support.annotation包下的

使用:

  • @SuppressWarnings(“”)
  • @SuppressWarnings({})
  • @SuppressWarnings(value={})

示例:

  • @SuppressWarnings(“unchecked”)

    告诉编译器忽略 unchecked 警告信息,如使用List,ArrayList等未进行参数化产生的警告信息。

  • @SuppressWarnings(“serial”)

    如果编译器出现这样的警告信息:The serializable class WmailCalendar does not declare a static final serialVersionUID field of type long

    使用这个注释将警告信息去掉。

  • @SuppressWarnings(“deprecation”)

    如果使用了使用@Deprecated注释的方法,编译器将出现警告信息。 
    使用这个注释将警告信息去掉。

  • @SuppressWarnings(“unchecked”, “deprecation”)

    告诉编译器同时忽略unchecked和deprecation的警告信息。

  • @SuppressWarnings(value={“unchecked”, “deprecation”})

    等同于@SuppressWarnings(“unchecked”, “deprecation”)

1、抑制单类型警告

@SuppressWarnings("unchecked")
public void addItems(String item){
  @SuppressWarnings("rawtypes")
   List items = new ArrayList();
   items.add(item);
}
  •  

2、抑制多类型警告

@SuppressWarnings(value={"unchecked", "rawtypes"})
public void addItems(String item){
   List items = new ArrayList();
   items.add(item);
}
  •  

3、抑制全部警告

@SuppressWarnings("all")
public void addItems(String item){
   List items = new ArrayList();
   items.add(item);
}
  •  

注解目标   
                               
通过 @SuppressWarnings 的源码可知,其注解目标为类、字段、函数、函数入参、构造函数和函数的局部变量。而家建议注解应声明在最接近警告发生的位置。

到这里基本注解都已经说完了,最后说明一下,如果函数库中使用Annotation Library,并使用Gradle生成aar压缩包,那么在编译时Android Gradle插件会取出这些注解信息并打包在aar文件中,以便函数库的调用者正常使用我们的注解信息。aar文件中的annotations.zip文件就是抽取出来的注解信息。

参考: 
@SuppressWarnings忽略警告 
《Android高级进阶》

© 著作权归作者所有

共有 人打赏支持
KingBoxing123
粉丝 5
博文 90
码字总数 48684
作品 0
成都
Android 网络编程 目录

Android 网络编程 目录 Android 网络编程1 Http协议 to be continued... Android 架构师之路 目录 Android 架构师之路1 UML图之用例图 Android 架构师之路2 UML图之类图 Android 架构师之路3...

香沙小熊 ⋅ 06/21 ⋅ 0

Matrix, ColorMatrix

作为Android源码中的一个常用类,它的作用是持有一个3*3的矩阵数组,用于坐标的转换。 Matrix用来制作动画效果、改变图片大小、给图片加各类滤镜等。 Matrix 的应用 - 压缩图像;Matrix 的应...

shareus ⋅ 04/13 ⋅ 0

android --------学习流程图

如何快速入门和进阶安卓开发,是很多技术小白的疑问。 大家都知道,Android开发要学的技能非常多,技术更新速度还快,但是总的来说:掌握最核心的技术,最规范的开发流程,成为专业、出色的安...

切切歆语 ⋅ 05/06 ⋅ 0

Android Hybrid开发:这是一份详细 & 全面的WebView学习攻略

前言 现在很多里都内置了Web网页(),比如说很多电商平台,淘宝、京东、聚划算等等,如下图 那么这种该如何实现呢?其实这是里一个叫组件实现 今天,我将献上一份全面 & 详细的 攻略,含具体...

Carson_Ho ⋅ 06/19 ⋅ 0

AndroidManifest.xml详解

我们在进行APP开发的时候都会遇到一个文件:AndroidManifest.xml。从刚开始进行Android开发,到现在已经过去了几个月,还是对这个文件一知半解,只知道它是配置用的。但是这文件里的东西具体...

闪电的蓝熊猫 ⋅ 05/14 ⋅ 0

Android动画:献上一份详细 & 全面的动画知识学习攻略

前言 动画的使用 是 开发中常用的知识 可是动画的种类繁多、使用复杂,每当需要 采用自定义动画 实现 复杂的动画效果时,很多开发者就显得束手无策 本文将献上一份动画的全面介绍攻略,包括动...

Carson_Ho ⋅ 06/06 ⋅ 0

Android RxJava: 这是一份全面的 操作符 使用汇总 (含详细实例讲解)

前言 ,由于其基于事件流的链式调用、逻辑简洁 & 使用简单的特点,深受各大 开发者的欢迎。 如果还不了解RxJava,请看文章:Android:这是一篇 清晰 & 易懂的Rxjava 入门教程 如此受欢迎的原...

Carson_Ho ⋅ 05/31 ⋅ 0

SupportAnnotation和AndroidAnnotations

截个图,大概annotations 包中有40个注解,看名称一般就知道是干什么的了, 这个是 support-annotations-23.1.1 中的所有的注解, ===================另外一个开源的注解框架=================...

新年 ⋅ 2016/01/19 ⋅ 0

Android Camera&Matrix图像变换

Camera与Matrix Android UI系统中,Camera充当着相机的角色,无论是系统成像还是UI绘制。都离不开Camera。但是在Android系统中,存在两种Camera,一种是视觉成像的(拍照、摄像),另一种是图...

IamOkay ⋅ 04/04 ⋅ 0

Android 性能优化:手把手教你优化Bitmap图片资源的使用

前言 在 开发中,性能优化策略十分重要 本文主要讲解性能优化中的Bitmap 使用优化,希望你们会喜欢 目录 1. 优化原因 即 为什么要优化图片资源,具体如下图:

Carson_Ho ⋅ 04/24 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

tcp/ip详解-链路层

简介 设计链路层的目的: 为IP模块发送和接收IP数据报 为ARP模块发送ARP请求和接收ARP应答 为RARP模块发送RARP请求和接收RARP应答 TCP/IP支持多种链路层协议,如以太网、令牌环往、FDDI、RS-...

loda0128 ⋅ 57分钟前 ⋅ 0

spring.net aop代码例子

https://www.cnblogs.com/haogj/archive/2011/10/12/2207916.html

whoisliang ⋅ 今天 ⋅ 0

发送短信如何限制1小时内最多发送11条短信

发送短信如何限制1小时内最多发送11条短信 场景: 发送短信属于付费业务,有时为了防止短信攻击,需要限制发送短信的频率,例如在1个小时之内最多发送11条短信. 如何实现呢? 思路有两个 截至到当...

黄威 ⋅ 昨天 ⋅ 0

mysql5.7系列修改root默认密码

操作系统为centos7 64 1、修改 /etc/my.cnf,在 [mysqld] 小节下添加一行:skip-grant-tables=1 这一行配置让 mysqld 启动时不对密码进行验证 2、重启 mysqld 服务:systemctl restart mysql...

sskill ⋅ 昨天 ⋅ 0

Intellij IDEA神器常用技巧六-Debug详解

在调试代码的时候,你的项目得debug模式启动,也就是点那个绿色的甲虫启动服务器,然后,就可以在代码里面断点调试啦。下面不要在意,这个快捷键具体是啥,因为,这个keymap是可以自己配置的...

Mkeeper ⋅ 昨天 ⋅ 0

zip压缩工具、tar打包、打包并压缩

zip 支持压缩目录 1.在/tmp/目录下创建目录(study_zip)及文件 root@yolks1 study_zip]# !treetree 11└── 2 └── 3 └── test_zip.txt2 directories, 1 file 2.yum...

蛋黄Yolks ⋅ 昨天 ⋅ 0

聊聊HystrixThreadPool

序 本文主要研究一下HystrixThreadPool HystrixThreadPool hystrix-core-1.5.12-sources.jar!/com/netflix/hystrix/HystrixThreadPool.java /** * ThreadPool used to executed {@link Hys......

go4it ⋅ 昨天 ⋅ 0

容器之上传镜像到Docker hub

Docker hub在国内可以访问,首先要创建一个账号,这个后面会用到,我是用126邮箱注册的。 1. docker login List-1 Username不能使用你注册的邮箱,要用使用注册时用的username;要输入密码 ...

汉斯-冯-拉特 ⋅ 昨天 ⋅ 0

SpringBoot简单使用ehcache

1,SpringBoot版本 2.0.3.RELEASE ①,pom.xml <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.3.RELE......

暗中观察 ⋅ 昨天 ⋅ 0

Spring源码解析(八)——实例创建(下)

前言 来到实例创建的最后一节,前面已经将一个实例通过不同方式(工厂方法、构造器注入、默认构造器)给创建出来了,下面我们要对创建出来的实例进行一些“加工”处理。 源码解读 回顾下之前...

MarvelCode ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部