Android新增的注解
环境
使用Android注解前需要导入相关的包
compile 'com.android.support:support-annotations:latest.integration'
注意:如果我们已经引入了appcompat则没有必要再次引用support-annotations,因为appcompat默认包含了对其引用
使用
Android注解给我们提供了三种主要和其他注释供我们使用:
IntDef和StringDef注解;
资源类型注解;
Null注解;
其他实用注解
IntDef和StringDef注解替代枚举
这里我们采用假设一个问题然后一步步解决学习:假设有一个User对象,我们需要记录user类型的变量,如何实现呢?
方案一
public class UserI {
public static int childe=0x1;
public static int man=0x2;
public static int girl=0x3; private int userType; public int getUserType() {
return userType;
} public void setUserType(int userType) {
this.userType = userType;
}
}
估计大家常用的就是这样的方式去解决这样的需求,但是上述实现存在一个问题:setUserType
设置的是一个int
类型的变量,既然如此我们可以如此调用:
UserI userI=new UserI();
/*正确调用*/
userI.setUserType(userI.childe); /*错误调用*/
userI.setUserType(100);
错误方式下的调用也不会抛出异常,所以这样的实现方式存在逻辑泄漏的危险!
方案二
既然如此:想必这个时候大家想到的解决办法就是枚举了,下面研究下枚举的实现
public class UserE { private UserEmun userType; public UserEmun getUserType() {
return userType;
} public void setUserType(UserEmun userType) {
this.userType = userType;
} public static enum UserEmun {
childe,
man,
girl
}
} 调用: UserE userE=new UserE();
userE.setUserType(UserE.UserEmun.childe);
从实现方式和逻辑上看,方案二枚举确实能解决方案一存在的漏洞,但是这里有一点需要注意:Enum
因为其相比方案一的常量来说,占用内存相对大很多而受到曾经被Google
列为不建议使用。
既然枚举也有它相关的缺陷,那如何完美解决这样的需求呢,以下完美实现-就是Android
中用注解来替换java
的枚举;
完美方案
Android中
新引入的替代枚举的注解有IntDef
和StringDef
,他们唯一的区别一个是int
类型,一个是string
类型,下面我们就以IntDef
为例讲解如何使用
构建定义注解
public class UserInter {
public static final int childe = 0x1;
public static final int man = 0x2;
public static final int girl = 0x3;
public static final int other = 0x4; @IntDef({childe, man, girl})
@Retention(RetentionPolicy.SOURCE)
public @interface UserInters{} }
@Retention
表示注解类型的存活时长和@interface
定义一个注解,具体详细用法可查看上章Java注解
注意:这里定义的other
并没有用IntDef
修饰
使用:
设置变量,设置get和set方法
public class UserInter {
public static final int childe = 0x1;
public static final int man = 0x2;
public static final int girl = 0x3;
public static final int other = 0x4; @IntDef({childe, man, girl})
@Retention(RetentionPolicy.SOURCE)
public @interface UserInters{} private int userType; @UserInters
public int getUserType() {
return userType;
} public void setUserType(@UserInters int userType) {
this.userType = userType;
}
}
使用我们自定义的注解类UserInters
,在get
方法上定义返回类型,和set
方法中设置传入参数的类型,这样在调用get
和set
方法时,编译器会自动帮我们检测是否合法!
UserInter userInter=new UserInter();
userInter.setUserType(UserInter.childe); userInter.setUserType(UserInter.other);
在调用的地方我们先正确的设置一个IntDef
定义的childe
,再设置一个没有用IntDef
修饰的other
对象:
结果:
从结果图片中可以发现,当设置一个没有被IntDef
定义的对象时,编译器直接抛出了异常,到此我们就完美解决了第一种方案的泄露和第二中方案中的占用内存相对大的问题;
资源类型注解
常用的资源注解:
name | exp |
---|---|
AnimRes | 动画 |
AnimatorRes | animator资源类型 |
AnyRes | 任何资源类型 |
ArrayRes | 数组资源类型 |
AttrRes | 属性资源类型 |
BoolRes | bool类型资源类型 |
ColorRes | 颜色资源类型 |
DimenRes | 长度资源类型 |
DrawableRes | 图片资源类型 |
IdRes | 资源id |
InterpolatorRes | 动画插值器 |
LayoutRes | layout资源 |
MenuRes | menu资源 |
RawRes | raw资源 |
StringRes | 字符串资源 |
StyleRes | style资源 |
StyleableRes | Styleable资源类型 |
TransitionRes | transition资源类型 |
XmlRes | xml资源 |
资源注解是为了防止我们在使用程序资源的时候,错误传递资源类型给函数,导致程序错误!
@StringRes 如例讲解:
public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); testDo(R.style.AppTheme);
testDo(R.string.app_name);
} private void testDo(@StringRes int str){
Log.e("tag","-------->"+getString(str));
} }
我们定义testDo
方法传入类型用@StringRes修饰,当方法被调用后编译器会自动匹配和检测,错误会及时的抛出错误异常,所以当调用testDo(R.style.AppTheme);
系统抛出异常如图
Null注解
null注解对应的有两个详细的注解:
@NonNull:不能为空
@Nullable:可以为空
使用@NonNull注解修饰的参数不能为null。在下面的代码例子中,我们有一个取值为null的msg变量,它被作为参数传递给testDo函数,而该函数要求这个参数是非null的String类型
public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); String msg=null;
testDo(msg);
} private void testDo(@NonNull String s){
Log.e("tag","-------->"+s);
}
}
结果:
编译器提示警告
@Nullable和@NonNull是相反的,使用一样,不啰嗦了!
注意:在使用的过程中发现在最新版本的AndroidStudio中不添加@Nullable和@NonNull,编译器也同样会提示响应的警告,所以这个注解可以忽略使用
其他注解
除了上述的主要功能注解外,还有一些实用的注解
Threading 注解
thread注解是帮助我们指定方法在特定线程中执行处理,如果和指定的线程不一致,抛出异常;Threading 注解类型:
@UiThread: UI线程
@MainThread :主线程
@WorkerThread: 子线程
@BinderThread : 绑定线程
下面以@WorkerThread为例:
public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); testDo(R.string.app_name);
} @WorkerThread
private void testDo(@StringRes int str){
Log.e("tag","-------->"+getString(str));
} }
错误提示结果:
我们指定testDo在子线程中处理,但是当前调用确实在主线程中,所以抛出异常
正确使用:
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() {
testDo(R.string.app_name);
}
});
} @WorkerThread
private void testDo(@StringRes int str){
Log.e("tag","-------->"+getString(str));
} }
结果:
Value Constraints注解
主要类型:
@Size
@IntRange
@FloatRange
@size使用
定义长度大小,可选择最小和最大长度使用
public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testDo(""); testDo("111"); testDo("1");
} private void testDo(@Size(min = 1,max = 2)String s){
Log.e("tag","-------->"+s);
}
}
错误提示结果:
这里size定了一个最小和最大长度,所以只有testDo("1")
符合条件,其他调用都抛出了异常
@IntRange使用
IntRange是用来指定int类型范围的注解
public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); testDo(0); testDo(2); } private void testDo(@IntRange(from = 1,to = 100)int s){
Log.e("tag","-------->"+s);
} }
用IntRange定义了一个从1到100的s类型,所以在调用testDo
方法时testDo(0)
不符合要求,会抛出异常
错误提示结果:
@FloatRange使用
FloatRange和IntRange用法一样,不过是指定的是float类型的数据对象,不重复阐述了
使用:
public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); testDo(0); testDo(2);
} private void testDo(@FloatRange(from = 1.0,to = 100.0)float s){
Log.e("tag","-------->"+s);
} }
错误提示结果:
@CallSuper注解
@CallSuper
注解主要是用来强调在覆盖父类方法时,需要实现父类的方法,及时调用对应的super.***
方法,当用@CallSuper
修饰了该方法,如果子类覆盖的后没有实现对呀的super
方法会抛出异常
正常使用:
public class CallSuperT { @CallSuper
protected void init(){ } class T extends CallSuperT{ @Override
protected void init() {
super.init();
}
}
}
首先定义一个CallSuperT
父类,然后生成一个T
继承CallSuperT
覆盖其init()
方法,父类中的init()
采用@CallSuper定义,如果我们去掉子类覆盖的super.init();
方法,AS在编译时会抛出错误信息
修改:
public class CallSuperT { @CallSuper
protected void init(){ } class T extends CallSuperT{ @Override
protected void init() {
}
}
}
错误提示结果:
@CheckResult注解
假设你定义了一个方法返回一个值,你期望调用者用这个值做些事情,那么你可以使用@CheckResult注解标注这个方法,强制用户定义一个相应的返回值,使用它!
使用:
首先修改上面的CallSuperT
,定义一个retrunI
方法返回一个int
类型
public class CallSuperT { @CheckResult
public int retrunI(){
return 1;
}
}
正确调用:
public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); CallSuperT callSuperT = new CallSuperT();
int returns = callSuperT.retrunI();
}
}
如果这里去掉返回类型的定义对象:int returns
则会抛出异常
public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); CallSuperT callSuperT = new CallSuperT();
callSuperT.retrunI();
}
}
错误提示结果:
总结:
注解的作用:
提高我们的开发效率
更早的发现程序的问题或者错误
更好的增加代码的描述能力
更加利于我们的一些规范约束
提供解决问题的更优解
使用Java注解和Android注解,能大幅度的提高我们的开发效率已经开发过程中的及时校验,避免一些因开发者疏忽而导致的问题,非常的实用!
Android新增的注解的更多相关文章
- Android中通过注解代替findViewById方法
转自:http://www.2cto.com/kf/201405/302998.html 这篇文章主要讲解注解实现findViewById的功能,首先我们来熟悉一下在java中怎么定义一个注解和解析一 ...
- 2.2、Android Studio通过注解提升代码检测
使用像Lint这样的代码检测工具可以帮助你发现问题和提升代码,但是代码检测在有些地方很难应用.例如,Android的资源ID,使用一个int类型来表示字符.图像.颜色或者其他资源类型所以代码检测工具不 ...
- 8 -- 深入使用Spring -- 2...5 Spring 3.0 新增的注解
8.2.5 Spring 3.0 新增的注解 @DependsOn @Lazy @DependsOn :用于强制初始化其他Bean.修饰Bean类或方法,可以指定一个字符串数组作为参数,每个数组元素对 ...
- 利用APT实现Android编译时注解
摘要: 一.APT概述 我们在前面的java注解详解一文中已经讲过,可以在运行时利用反射机制运行处理注解.其实,我们还可以在编译时处理注解,这就是不得不说官方为我们提供的注解处理工具APT (Anno ...
- 理解Android中的注解与反射
反射 Java反射(Reflection)定义 Java反射机制是指在运行状态中 对于任意一个类,都能知道这个类的所有属性和方法:对于任何一个对象,都能够调用它的任何一个方法和属性: 这样动态获取新的 ...
- Android运行时注解
Android的注解有编译时注解和运行时注解,本文就介绍下运行时注解. 其实非常简单,直接上代码:本文主要是替代传统的findViewById()的功能,就是在我们Activity中不需要再使用fin ...
- Android 编译时注解解析框架
2.注解 说道注解,竟然还有各种分类,得,这记不住,我们从注解的作用来反推其分类,帮助大家记忆,然后举例强化大家的记忆,话说注解的作用: 1.标记一些信息,这么说可能太抽象,那么我说,你见过@Over ...
- Android开发之注解式框架ButterKnife的使用
ButterKnife官网 其实ButterKnife的注解式,与xUtils的ViewUtils模块基本上差不多,只要用过xUtils,这个框架基本上就会了. 一.原理. 最近发现一个很好用的开源框 ...
- Android AOP之路三 Android上的注解
一.简单介绍 啥是注解.不懂的能够先看我上一篇文章. 在android 里面 注解主要用来干这么几件事: 和编译器一起给你一些提示警告信息. 配合一些ide 能够更加方便快捷 安全有效的编写java代 ...
随机推荐
- Spring中application*的使用
ApplicationAware 加载Spring配置文件时,如果Spring配置文件中所定义的Bean类实现了ApplicationContextAware 接口,那么在加载Spring配置文件时, ...
- Vue之cookie操作(原生)
Vue之cookie操作(原生) 再vue组件中加入以下几个方法,然后调用即可. methods:{ //读取cookie,需要注意的是cookie是不能存中文的,如果需要存中文,解决方法是后端先进行 ...
- angularjs之向下一个页面传参
原理: 1.在a标签跳转时,连接后增加一个参数值 2.在路由中接收 3.在控制器中接收 实现: 1.<a href="#/list/{{val.id}}"> 2.在js ...
- JS倒计时,自动提交表单!
<form id="frm" action="http://www.baidu.com"> 考试还剩余<div id="time&q ...
- UNITY所谓的异步加载几乎全部是协程,不是线程;MAP3加载时解压非常慢
实践证明,以下东西都是协程,并非线程(thread): 1,WWW 2,AssetBundle.LoadFromFileAsync 3,LoadSceneAsync 其它未经测试 此问题的提出是由于一 ...
- Hibernate的HQL中in参数设置
平时经常用Hibernate,由于习惯表间不建立关联,所以HQL查询时候经常要用in语句. 我最常用的情况有2种: 1.in后是个子查询,如 FROM A WHERE A.ID IN (SELECT ...
- 打包jar文件并自动运行
1,首先在eclipse 或MyEclipse 中测试通过,没有问题,(每次修改要update Maven) 2,修改pom.xml ---把build中改为<excludes> < ...
- Oracle中关于DateTime的一些描述
转载自:http://www.cnblogs.com/fmxyw/archive/2008/08/26/1276850.html 在做话务报表,参考一下信息 to_date()与24小时制表示法及 ...
- css常用属性总结第二弹:id选择器
承接上一篇class选择器,这一篇我们来说说css的id选择器. id选择器类似于类选择器,不过也有一些重要的差别,首先,id选择器前面有一个#号----称它为棋牌号吧,class为点号,用法就和cl ...
- js闭包的定义
通过函数字面量创建的函数对象包含一个连接到外部上下文的连接,这叫做闭包. 还有一种定义:函数可以访问它被创建时所处的上下文环境,叫做闭包.