使用andrid注解进行更高效地开发
在使用之前,先引入annotations库
compile 'com.android.support:support-annotations:{version}'
空值判断注解
- @Nullable 使用@Nullable修饰的参数可以取null值
- @NonNull
使用NonNull修饰的参数不能取null值,如果赋予了null值,ide将会警告我们
举个栗子
public class Test{ private int num; public void setNum(@NonNull int n){ this.num=n; } }
资源类型注解
常用的资源类型注解如下
注解 | 功能 |
---|---|
AnyRes | 用来标注一个未知的特殊类型的资源,但是它必须是一个资源类型 |
@AnimatorRes | 标记类型为android.R.animator资源类型 |
@AnimRes | 标记类型为android.R.anim资源类型,注意与AnimatorRes的区别,两者的包名不同 |
@ArrayRes | 标记类型为android.R.array资源类型 |
@AttrRes | 标记类型为android.R.attr资源类型 |
@BoolRes | 记类型为android.R.boolean资源类型 |
@ColorRes | 标记类型为android.R.color资源类型 |
@DimenRes | 标记类型为android.R.dimen资源类型 |
@DrawableRes | 标记类型为android.R.标记类型为android.R.drawable资源类型 |
@FractionRes | 标记类型为android.R.fraction资源类型,这个类型比较少见,常见于Animation.xml中,例如30%p,表示占parent的30% |
@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资源类型 |
@StyleRes | 标记类型为android.R.style资源类型 |
@StyleableRes | 标记类型为android.R.transition资源类型 |
@TransitionRes | 标记类型为android.R.transition资源类型 |
@XmlRes | 标记xml类型的文件 |
类型定义注解
类型定义注册可以让我们自己定义枚举类型并标注相应的参数
- @IntDef
定义一组整数型枚举值,假如传入或者返回的值不是枚举中的值的时候,ide将给出提示
举个栗子:
public class IntDefTest{ private int result; public static final int NO=0; public static final int YES=1; @IntDef{NO,YES} public @interface YesOrNo{} @YesOrNo public int getResult(){ return result; } public void setResult(@YesOrNo int r){ this.result=r; } }
- @StringDef
定义一组String类型的枚举值,用法与@IntDef相同
##权限注解
如果你的方法的调用需要调用者有特定的权限,你可以使用@RequiresPermission注解
@RequiresPermission(Manifest.permission.SET_WALLPAPER) public abstract void setWallpaper(Bitmap bitmap) throws IOException;
如果你至少需要权限集合中的一个,你可以使用anyOf属性:
@RequiresPermission(anyOf = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}) public abstract Location getLastKnownLocation(String provider);
如果你同时需要多个权限,你可以用allOf属性
@RequiresPermission(allOf = { Manifest.permission.READ_HISTORY_BOOKMARKS, Manifest.permission.WRITE_HISTORY_BOOKMARKS}) public static final void updateVisitedHistory(ContentResolver cr, String url, boolean real);
线程注解
Android中提供了四个与线程相关的注解,他们分别是
- @UiThread,通常可以等同于主线程,标注方法需要在UIThread执行,比如View类就使用这个注解
- @MainThread 主线程,经常启动后创建的第一个线程
- @WorkerThread 工作者线程,一般为一些后台的线程,比如AsyncTask里面的doInBackground就是这样的.
- @BinderThread 注解方法必须要在BinderThread线程中执行,一般使用较少.
其他注解
- @CallSuper 方法重写 如果你的API允许使用者重写你的方法,但是呢,你又需要你自己的方法(父方法)在重写的时候也被调用,这时候你可以使用@CallSuper标注,拥有这个注解,ide会强制要求调用super方法
- @CheckResult 检测返回值
如果你的方法返回一个值,你期望调用者用这个值做些事情,那么你可以使用@CheckResult注解标注这个方法。
Android中,Context#checkPermission这个方法已经被@CheckResult标注了:@(suggest="#enforcePermission(String,int,int,String)") public abstract int checkPermission(@NonNull String permission, int pid, int uid)
这是非常重要的,因为有些使用context.checkPermission的开发者认为他们已经执行了一个权限 —但其实这个方法仅仅只做了检查并且反馈一个是否成功的值而已。如果开发者使用了这个方法,但是又不用其返回值,那么这个开发者真正想调用的可能是这个Context#enforcePermission方法,而不是checkPermission。