Android Support Library从19.1版本开始引入了一个新的注解库,其中包括了很多有用的元注解,可以用来修饰代码并且帮助发现bug。Support Library本身也使用了这些注解来完善自身的代码质量,Android Studio 天然地支持Annotation Library,并提供可视化的交互以方便开发者发现问题。
如何使用注解库
步骤1:
点击Project Structure按钮
步骤2:
选中Dependencies标签,点击“+”号按钮
步骤3:
在下拉列表中选中support-annotations库
点击OK确定,这将会修改build.gradle文件。当然也可以手动在Gradle中添加如下依赖:
dependencies {
compile 'com.android.support:support-annotations:25.0.1'
}
注解类型
1.Nullness注解
@Nullable注解可以用来标识特定的参数或者返回值可以为null。
类似的,@NonNull注解可以用来标识参数不能为null。
下面的用@NonNull检查context和attrs参数不为空,同样也可以检查oncreateview()方法不为空
import android.support.annotation.NonNull;
...
/** Add support for inflating the <fragment> tag. **/
@NonNull
@Override
public View onCreateView(String name, @NonNull Context context,
@NonNull AttributeSet attrs) {
...
}
...
2.资源类型注解(Resource Annotations)
资源类型的注解作用于函数参数、返回值及类的变量,在support-annotations中,每种资源类型对应一个注解。(部分注解)
@DrawableRes, 标记整型值是android.R.drawable类型
@DimenRes, 标记整型值是android.R.dimen类型
@ColorRes,标记整型值是android.R.color类型
@InterpolatorRes,标记整型值是android.R.interpolator类型
@AnyRes,标记整型值是android.R.any类型
@StringRes, 标记整型值是android.R.string类型
@AnimRes, 标记整型值是android.R.anim类型
例如,用@StringRes来检查
public abstract void setTitle(@StringRes int resId) { … }
3.线程注解(Thread Annotations)
Android 应用开发过程中,经常会涉及多种线程的使用,界面相关操作必须在主线程,而耗时的操作放在后台线程中执行。下面的线程注解都支持:
@MainThread
@UiThread
@WorkerThread
@BinderThread
@AnyThread
比较典型的是AsyncTask的实现:
@mainThread
protected void onPreExecute(){}
@WorkerThread
protected abstract Result doInBackground(Params... params);
@MainThread
protected void onProgressUpdate(Progress... values) {};
4.值范围注解(Value Constraint Annotations)
当函数参数的取值是在一定范围内时,可以使用值范围注解来防止调用者传入错误的参数,这种类型主要有三种注解。
(1)@Size:用来注解类似数组、集合和字符串之类的参数的大小。用法如下:
Minimum size (such as @Size(min=2))
Maximum size (such as @Size(max=2))
Exact size (such as @Size(2))
A number of which the size must be a multiple (such as @Size(multiple=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) {...}
5.权限注解(Permission Annotations)
开发Android应用时,在使用某些系统功能是,需要在AndroidMainfest.xml 中声明权限,否则在运行时会提示缺失对应的权限。为了在编译期及时发现缺失的权限,可以使用@RequiresPermission注解。
(1)函数调用声明权限的用法如下:
@RequiresPermission(Manifest.permission.SET_WALLPAPER)
public abstract void setWallpaper(Bitmap bitmap) throws IOException;
(2)函数调用声明集合中最少一个权限的用法如下:
@RequiresPermission(allOf = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE})
public static final void copyFile(String dest, String source) {
...
}
(3)Intent 调用权限,可以在Intent的ACTION字符串定义处添加注解,用法如下:
@RequiresPermission(android.Manifest.permission.BLUETOOTH)
public static final String ACTION_REQUEST_DISCOVERABLE =
"android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
(4)对于ContentProvider相关所需的权限,可能同时需要读和写这两个操作,对应不同的权限声明,用法如下:
@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
6.返回值注解(Return Value Annotations)
如果我们编写的函数需要调用这对返回值做某些处理,那么可以使用@CheckResult注解来提示开发者。
@CheckResult(suggest="#enforcePermission(String,int,int,String)")
public abstract int checkPermission(@NonNull String permission, int pid, int uid);
7.重写函数注解(CallSuper Annotations)
如果Api允许调用者重写某个函数,但同时要求重写的函数需要调用被重写的函数,否则代码逻辑可能会错误,那么可以使用@CallSupper注解来提示开发者。
@CallSuper
protected void onCreate(Bundle savedInstanceState) {
}
8.类型定义注解(Typedef Annotations)
@IntDef注解用来创建一个整型类型定义的新注解,我们可以使用这个新注解来标记编写的API。
import android.support.annotation.IntDef;
...
public abstract class ActionBar {
...
// Define the list of accepted constants and declare the NavigationMode annotation
@Retention(RetentionPolicy.SOURCE)
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
public @interface NavigationMode {}
// Declare the constants
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
// Decorate the target methods with the annotation
@NavigationMode
public abstract int getNavigationMode();
// Attach the annotation
public abstract void setNavigationMode(@NavigationMode int mode);