目录
- android中的注解使用
- 定义
- 常用注解
- @Target
- @Retention
- @Document
- android中注解
- 资源相关
- AnimatorRes
- AnimRes
- AnyRes
- ArrayRes
- BoolRes
- ColorRes
- DimenRes
- DrawableRes
- FontRes
- FractionRes
- IntegerRes
- InterpolatorRes
- LayoutRes
- MenuRes
- NavigationRes
- PluralsRes
- RawRes
- StringRes
- StyleableRes
- StyleRes
- TransitionRes
- XmlRes
- 类型def相关
- IntDef
- StringDef
- LongDef
- 类型NULL相关
- Nullable
- NonNull
- 区间范围相关
- IntRange
- FloatRange
- 长度限定相关
- Size
- 权限相关
- RequiresApi
- RequiresPermission
- 混淆相关
- Keep
- 回调相关
- CallSuper
- 常用相关类
- Override
- Deprecated
- TargetApi
- 线程相关类
- BinderThread
- UiThread
- WorkerThread
- MainThread
- AnyThread
- 自定义注解
- 总结
android中的注解使用
定义
Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和着任何元数据(metadata)的途径和方法。Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的 Annotion对象,然后通过 Annotion对象 来获取注解里面的元数据。
常用注解
@Target
修饰的对象范围,表示作用的范围。可以查看ElementType了解详情。
取值 | 范围 |
TYPE | 类、接口 |
FIELD | 字段、枚举 |
METHOD | 方法 |
PARAMETER | 方法形参 |
CONSTRUCTOR | 构造方法 |
LOCAL_VARIABLE | 局部变量 |
ANNOTATION_TYPE | 作用在注解上,即元注解 |
PACKAGE | 包 |
TYPE_PARAMETER | 类型参数(1.8后) |
TYPE_USE | 使用类型(1.8后) |
@Retention
表示注解的生命周期,在什么级别会保留或者遗弃。RetentionPolicy中可查看类型
策略 | 保留 | 有效期间 |
SOURCE | 源文件保留 | 编辑期间保留,动态检测,其他不会保留 |
CLASS | class文件中有效 | 记录在类文件中,不会被虚拟机保留 |
RUNTIME | 运行期有效 | 记录在类文件中,虚拟机保留 |
@Document
表示默认情况下,javadoc 和类似工具将记录带有类型的注释。此类型应用于注释类型的声明,这些声明的注释会影响其客户端对带注释的元素的使用。如果类型声明用记录,则其注释将成为带注释元素的公共API的一部分。
android中注解
android中的注解需要导入
implementation 'com.android.support:support-annotations:27.0.1'
里面的注解非常多,可以让代码逻辑更加规范。
资源相关
AnimatorRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是动画资源引用(例如{android.R.animator.fade_in})
AnimRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是动画资源引用(例如{@code android.R.anim.fade_in})
AnyRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是任意资源的引用
ArrayRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是数组资源引用(例如{@code android.R.array.phoneTypes})。
BoolRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是布尔资源引用。
ColorRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是颜色资源引用。{@code android.R.color.black}).
DimenRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是尺寸资源引用。{@code android.R.dimen.app_icon_size}).
DrawableRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是可绘制资源引用。{@code android.R.attr.alertDialogIcon}).
FontRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是字体资源引用。{@code android.R.R.font.myfont}).
FractionRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是分数资源引用。
IntegerRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是整数资源引用。{@code android.R.integer.config_shortAnimTime}
InterpolatorRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是插值期资源引用。{@code android.android.R.interpolator.cycle}
LayoutRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是布局资源引用。{@code android.R.layout.activity_main}
MenuRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是菜单资源引用。{@code R.menu.main}
NavigationRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是导航资源引用。{@code R.navigation.flow}
PluralsRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是复数资源引用。
RawRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是原始资源引用。{@code R.raw.movie}
StringRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是字符串资源引用。{@code R.string.ok}
StyleableRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是可样式话资源引用。{@code R.styleable.TextView_text}
StyleRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是样式资源引用。{@code R.styleable.TextAppearance}
TransitionRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是过渡资源引用。
XmlRes
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE
表示期望整数参数,字段或方法的返回值*是XML资源引用。
类型def相关
该类型下的注解有 IntDef 、LongDef和 StringDef 。是google用来代替简单类型枚举的注解。
IntDef
作用域:注解上
表示带有整数类型的带注释元素表示逻辑类型,并且其值应为明确命名的常量之一。如果IntDef#flag()属性设置为true,则可以组合多个常量。
创建新整型注解。
public static final int NET_4G = 0;
public static final int NET_5G = 1;
public static final int NET_WIFE = 2;
public static final int NET_3G = 3;
@IntDef({NET_4G, NET_5G, NET_WIFE, NET_3G})
@Retention(RetentionPolicy.SOURCE)
public @interface NetStatus {
}
使用其他非给定类型是会报错的。
StringDef
作用域:注解上
表示带有字符类型的带注释元素表示逻辑类型,并且其值应为明确命名的常量之一。
LongDef
作用域:注解上
表示带有字符类型的带注释元素表示逻辑类型,并且其值应为明确命名的常量之一。
类型NULL相关
Nullable
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE
表示参数,字段或方法的返回值可以为null。方法调用参数时,这表示该参数可以合法地为null,并且该方法将适当地处理它。通常用于可选参数。
NonNull
作用域:METHOD, PARAMETER, FIELD, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE
表示参数,字段或方法的返回值不能为null。
private void setTextView(@NonNull String string){
textView.setText(string);
}
区间范围相关
IntRange
作用域METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE
表示带注释的元素在给定范围内应为int或long。
public static void startMain(@Nullable Context context, @IntRange(from = 0,to = 3) int index) {
//fragment选中方法,防止越界
mBottomTab.setCurrentItem(index);
}
FloatRange
作用域METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE
表示带注释的元素在给定范围内应为float或double。
长度限定相关
Size
作用域:表示带注释的元素应具有给定的大小或长度。通常用来限定数组或者集合的大小,可支持常数大小或者范围。
public void getLocationInWindow(@Size(2) int[] location) {
...
}
private void setDateList(@NonNull @Size(min = 1,max = 100) ArrayList dateList){
......
}
权限相关
RequiresApi
作用域:TYPE,METHOD,CONSTRUCTOR,FIELD
表示带注释的元素只能在给定的API级别或更高级别上调用。用来限定或者警告超过预期版本号的api的使用。
@RequiresApi(16)
static class TaskStackBuilderApi16Impl extends TaskStackBuilderBaseImpl {
@Override
public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
int flags, Bundle options) {
intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
return PendingIntent.getActivities(context, requestCode, intents, flags, options);
}
}
RequiresPermission
作用域:ANNOTATION_TYPE,METHOD,CONSTRUCTOR,FIELD,PARAMETER
表示带注释的元素需要(或可能需要)一个或多个权限。
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
private void setNewStatus(@NetStatus int type) {
switch (type) {
case NET_4G:
......
break;
case NET_5G:
......
break;
case NET_WIFE:
......
break;
case NET_3G:
......
break;
default:
break;
}
}
RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public abstract Location getLastKnownLocation(String provider);
混淆相关
Keep
作用域:PACKAGE,TYPE,ANNOTATION_TYPE,CONSTRUCTOR,METHOD,FIELD
表示在构建时最小化代码时,不应删除带注释的元素。这通常用于仅通过反射访问的方法和类,因此编译器可能认为代码未使用。
当然,这个注释起作用,还需要一定条件:
- 设置minifyEnabled为true,打开混淆开关。
- 在proguard-rules.pro配置文件中加入以下规则
-keep,allowobfuscation @interface android.support.annotation.Keep
-keep @android.support.annotation.Keep class *
-keepclassmembers class * {
@android.support.annotation.Keep *;
}
回调相关
CallSuper
作用域:METHOD
表示任何覆盖方法也应调用父类此方法。是修饰在父类上的,最常见的生命周期。
//fragment中的
@CallSuper
public void onResume() {
mCalled = true;
}
如果子类不实现就会报错,如图:
常用相关类
Override
作用域:METHOD
表示方法声明旨在覆盖超类型中的方法声明。如果一个方法带有注释,则该注释类型的编译器必须生成一条错误消息。
Deprecated
作用域:CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE
注释为@Deprecated的程序元素是不鼓励程序员使用的元素,通常是因为这样做很危险,或者是因为存在更好的替代方法。就是方法过时,被抛弃使用了。
TargetApi
作用域:TYPE, METHOD, CONSTRUCTOR, FIELD
用于屏蔽某一新api中才能使用的方法报的lint检查出现的错误。简单来说,@TargetApi是给使用了此注解的方法添加访问权限。
线程相关类
BinderThread
作用域:METHOD,CONSTRUCTOR,TYPE,PARAMETER
表示期望整数参数,字段或方法的返回值要运行在binder线程中。
UiThread
作用域:METHOD,CONSTRUCTOR,TYPE,PARAMETER
表示期望整数参数,字段或方法的返回值要运行在ui线程中。
WorkerThread
作用域:METHOD,CONSTRUCTOR,TYPE,PARAMETER
表示期望整数参数,字段或方法的返回值要运行在worker线程中。
MainThread
作用域:METHOD,CONSTRUCTOR,TYPE,PARAMETER
表示期望整数参数,字段或方法的返回值要运行在主线程中。
AnyThread
作用域:METHOD,CONSTRUCTOR,TYPE,PARAMETER
*表示可以从任何线程调用带注释的方法(例如,它是“线程安全的”。)*如果带注释的元素是一个类,则可以从任何线程调用该类中的所有方法。
自定义注解
使用 @interface 自定义注解时,自动继承了 java.lang.annotation.Annotation 接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface 用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是 基本类型、Class、String、enum)。可以通过 default 来声明参数的默认值。
例子:性能差的findviewbyid
自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface ViewById {
int valueId() default 0;
}
将注解的类注入
public class ViewByIdImpl {
public static void injectActivity(Activity activity){
Class<?> aClass = activity.getClass();
Field[] fields = aClass.getDeclaredFields();
for (Field field : fields) {
ViewById annotation = field.getAnnotation(ViewById.class);
if(annotation != null){
View view = activity.findViewById(annotation.valueId());
field.setAccessible(true);
try {
field.set(activity,view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
public class TestTwoActivity extends AppCompatActivity {
@ViewById(valueId = R.id.tv_test_annotations)
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_one);
//注入
ViewByIdImpl.injectActivity(this);
textView.setText("注入生成");
}
}
总结
总的来说,注解能帮你优化代码,尤其是多人开发的时候,良好的注解习惯配合注释,使代码更清晰。减少传参异常、角标越界、空指针等bug的出现。而且还能使用apt技术自动化生成代码,比如黄油刀、dragger2等。