安卓进阶:元注解Support Annotation Library使用详解

摘要:
资源类型的注释作用于函数参数、返回值和类变量。每个资源类型对应一个注释。AnimRes:标记整数值是android.R.anim类型AnyRes:标签整数值是任何资源类型。如果您确切知道表示的是哪个特定资源,建议显示指定的值。FractionRes:标记整数值的类型为fraction,这是比较罕见的。这种类型的资源在AnimationXml中很常见。例如,50%p表示父级的50%。InterpolatorRes:标记整数值的类型为android.R.Interpolator。

Support Annotation Library是一个函数包,包含一系列有用的元注解。

注解目录:

实用主义至上,不记录历史和版本这些,现在直接了解一下这个函数包有什么用,知道作用了才有兴趣深入了解:

作用:

这些元注解可以帮助我们发现在开发中遇到的一些bug。凡是标注了元注解的地方在Proable bugs中,我们可以看到程序可能发生bug的地方,提前预知Bug在何处,提前避开bug。

使用步骤:

一、首先导入这个函数包,Android Studio是天然支持的。在project structure导入support-annotations这个包

安卓进阶:元注解Support Annotation Library使用详解第1张

二、对容易出错的类或者方法进行注解,下面写一个简单的Demo:   定义一个方法s(),对这个方法中的形参进行注解(蓝色字体是注解内容),注解为不可以为空,之后在主方法中调用这个方法,参数为空。

public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        s(null);

    }


    public String  s(@NonNull String s){
        return s;
    }


}

三、现在我们特意写的错误写好了,接下来对整个项目的代码进行检查,看看Android Studio给我们返回的效果:

检查代码步骤:

安卓进阶:元注解Support Annotation Library使用详解第2张

安卓进阶:元注解Support Annotation Library使用详解第3张

查看可能存在的bug:

安卓进阶:元注解Support Annotation Library使用详解第4张

可以看到在控制台的Probable bugs中可以看到给我们自己注解后如果操作错误提示的错误

这是我们使用这个注解库的终极目标,方便我们使用自定义的类和方法,也便于我们找到未知的bug,对团队间合作作用也挺大的,而且我们使用系统的一些方法和类出错时对这些错误的理解也很有帮助

下面介绍一些注解的使用方式:

 Nullness注解

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

举个例子:

定义一个test()方法,这个方法的形参是String类型,给定注解是可以为null

安卓进阶:元注解Support Annotation Library使用详解第5张

在onCreate()方法中调用这个方法

安卓进阶:元注解Support Annotation Library使用详解第6张 

 

 资源类型注解

   我们知道资源在Android中通常是以整型值表示的,并保存在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类型。
  • FractionRes:标记整型值是fraction类型,这个比较少见,这种类型的资源常见于Animation Xml中,比如50%p,表示占parent的50%。
  • IdRes:标记整型值是android.R.id类型。
  • IntegerRes:标记整型值是android.R.integer类型。
  • 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类型。 
  • StyleResult:标记整型值是android.R.style类型。
  • TransitionRes:标记整型值是transition类型。
  • XmlRes:标记整型值是android..R.xml类型。

看个例子:

我先自定义一个方法test(),在这个方法中有一个形参int i,给这个形参的注解是@LayoutRes

安卓进阶:元注解Support Annotation Library使用详解第7张

接下来我在onCreat()方法中调用这个test()方法,传入的参数也是int类型的,但是不是R.Layout类型的

 安卓进阶:元注解Support Annotation Library使用详解第8张

可以看到编译器会提示这个错误

类型定义注解

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

举个例子:

先自定义注解

安卓进阶:元注解Support Annotation Library使用详解第9张

调用注解好的方法看看效果

安卓进阶:元注解Support Annotation Library使用详解第10张

可以看到如果传入这个方法的参数不是常量列表中的常量的话编译器是会报错的

线程注解

  Android应用开发过程中,经常会涉及多种线程的使用,界面相关操作必须在主线程里,而耗时操作例如文件下载等则可以放到后台线程中。线程相关注解有四种

  • @UiThread:标记运行在UI线程,一个UI线程是Activity运行所在的主窗口,对于一个应用而言,可能存在多个UI线程,每个线程对应不同的主窗口
  • @MainThread:标记运行在主线程,一个应用只有一个主线程,主线程也是@UiThread线程。通常情况下,我们使用@MainThread来注解声明周期相关函数,使用@UiThread来注解视图相关函数,一般情况下,@UiThread和@MainThread是可以互换使用的
  • @WorkerThread:标记运行在后台线程。
  • @BinderThread:   标记运行在Binder线程。

一个很典型的例子就是AsyncTask的实现,下面我们自己来定义一个方法加上注解看看效果

package com.contentprovide.liuliu.test_4_21;

import android.os.Bundle;
import android.support.annotation.MainThread;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Thread(new Runnable() {
            @Override
            public void run() {
                a();
            }
        }).start();

    }

    @MainThread
    public void a() {
        Toast.makeText(getApplicationContext(), "123", Toast.LENGTH_LONG).show();
    }

}

在上面的代码中我自定义了一个方法a,给这个方法的元注解是@MainThread,然后在子线程new Thread()中调用这个方法,可以看到报以下错误

 安卓进阶:元注解Support Annotation Library使用详解第11张

RGB颜色值注解

  在资源类型注解中我们使用@ColorRes来标记参数类型需要传入颜色类型的资源id,而这里介绍的@ColorInt注解则是标记参数类型需要传入RGB或者ARGB颜色整型值。以下是TextView中的setTextColor()方法,这个方法的注解就是RGB颜色类型值,所以如果传入颜色类型的资源id就会报下面的错误

 安卓进阶:元注解Support Annotation Library使用详解第12张

值范围注解

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

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

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

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

  @Size(2)//可以表示数元素个数是2个

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

  (2)@IntRange:参数类型是int或者long,用法如下。

安卓进阶:元注解Support Annotation Library使用详解第13张

  (3)@FloatRange:参数类型是float或者double,用法如下。

安卓进阶:元注解Support Annotation Library使用详解第14张

权限注解

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

  •   如果函数调用需要声明一个权限,语句如下。
@RequiresPermission(Manifest.permission.SET_WALLPAPER)
  •   如果函数调用需要声明集合中最少一个权限,语句如下。
@RequiresPermission(anyOf = {
          Manifest.permission.ACCESS_CHECKIN_PROPERTIES,
          Manifest.permission.ACCESS_FINE_LOCATION
  })
  •   如果调用函数要同时声明多个权限,语句如下。
@RequiresPermission(allOf = {
          Manifest.permission.ACCESS_CHECKIN_PROPERTIES,
          Manifest.permission.ACCESS_FINE_LOCATION
  })
  •   对于Intent调用所需权限,可以在Intent的ACTION字符串定义处添加注解,语句如下。
@RequiresPermission(Manifest.permission.BLUETOOTH)
    public static final String ACTION_REQUEST_DISCOVERABLE= "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
  •    对于ContentProvider相关的所需权限,可能同时需要读和写这两个操作,对应不同的权限声明,语句如下。
@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
  @RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))

重写函数注解

  如果API允许调用者重写某个函数,但同时要求重写的函数需要调用被重写的函数,否者代码逻辑可能会错误,那么可以使用@CallSuper注解来提示开发者,语句如下是:

@CallSuper
    protected void onCreate(Bundle savedInstanceState);

 但是其实我一直不知道这个注解和@Override的区别在哪里,有大神知道麻烦留言告诉我一下,谢谢啦。

返回值注解

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

@VisibleForTesting

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

@Keep

  @Keep注解用来标记在Proguard混淆过程中不需要混淆的类或者方法。

最后啰嗦:如果函数库中使用了Annotation Library,并使用Gradle生成ll压缩包,那么在编译时Android Gradle插件会抽取出这些注解信息并打包在ll文件中,以便函数库的调用者正常使用我们的注解信息。ll文件中的annotations.zip文件就是抽取出来的注解信息

免责声明:文章转载自《安卓进阶:元注解Support Annotation Library使用详解》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇HTTP RFC(自学心得)sql把一段时间分割成周,月,季度,年的时间段下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

WebBrowser介绍——Javascript与C++互操作

WebBrowser控件是Microsoft提供的一个用于网页浏览的客户端控件,WebBrowser控件的使用相当广泛,例如很多邮件客户端都是使用可编辑的WebBrowser控件作为写邮件的工具,也有很多软件用WebBrowser控件弹出网页,如qq的新闻首页。 微软的MFC和.NET都有WebBrowser控件,这两个控件虽然容易上手,不过由于包装的太好...

Qt线程的简单使用(一)——通过QObject::moveToThread()创建线程

Qt中线程的一种创建方式,就是使用QObject::moveToThread()函数。如下,直接上源代码,可以把费时的任务放到doWork()方法里进行,不阻塞主线程。 1 #ifndef WORKER_H 2 #define WORKER_H 3 4 #include <QObject> 5 6 class Worker : public...

【STM32H7】第3章 ThreadX操作系统介绍

论坛原始地址(持续更新):http://www.armbbs.cn/forum.php?mod=viewthread&tid=99514 第3章   ThreadX操作系统介绍 本章节介绍 ThreadX 操作系统,让大家对 ThreadX 有一个整体的了解。 3.1 初学者重要提示 3.2 Express Logic公司介绍 3.3 ThreadX...

用windbg分析一个dead lock的问题

难得Winform项目中碰到dead lock,记录一下。 QA报告说,有时候晚上跑完自动化脚本,第二天早上来发现系统hang在屏保界面没反应,从日志看也没有报错。这种属于很少才会发生,也不知道怎么重现,但是很严重的bug,于是抓个dump来研究一下。 # Windbg加载dump文件后的一些文件信息 Microsoft (R) Windows Debu...

GDB常用调试命令以及多进程多线程调试

http://blog.csdn.net/freeelinux/article/details/53700266 一:普通命令   1.list命令 list  linenum      显示程序第linenum行周围的程序 list  function      显示函数名为function的函数的源程序 list                  ...

java面试宝典

相关概念 面向对象的三个特征 封装,继承,多态.这个应该是人人皆知.有时候也会加上抽象. 多态的好处 允许不同类对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用).主要有以下优点: 可替换性:多态对已存在代码具有可替换性. 可扩充性:增加新的子类不影响已经存在的类结构. 接口性:多态是超累通过方法签名...