使用andrid注解进行更高效地开发

在使用之前,先引入annotations库

compile 'com.android.support:support-annotations:{version}'

空值判断注解

  1. @Nullable 使用@Nullable修饰的参数可以取null值
  2. @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类型的文件

类型定义注解

类型定义注册可以让我们自己定义枚举类型并标注相应的参数

  1. @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;
     }
    }
    
  2. @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中提供了四个与线程相关的注解,他们分别是

  1. @UiThread,通常可以等同于主线程,标注方法需要在UIThread执行,比如View类就使用这个注解
  2. @MainThread 主线程,经常启动后创建的第一个线程
  3. @WorkerThread 工作者线程,一般为一些后台的线程,比如AsyncTask里面的doInBackground就是这样的.
  4. @BinderThread 注解方法必须要在BinderThread线程中执行,一般使用较少.

其他注解

  1. @CallSuper 方法重写 如果你的API允许使用者重写你的方法,但是呢,你又需要你自己的方法(父方法)在重写的时候也被调用,这时候你可以使用@CallSuper标注,拥有这个注解,ide会强制要求调用super方法
  2. @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。