前言:使用SupportAnnotations优化代码本文讲解了如何使用SupportAnnotations优化代码,比如使用android特有的魔法变量注解替代Enum等函数。不要看到注解就认为反射会影响性能。今天我们就来学习一下AndroidSupportAnnotations注解来优化我们的代码,增加可读性,让更多的错误消除在萌芽状态。SupportAnnotations简介:Android支持库不断引入新的注解库,其中包含许多有用的元注解,您可以使用它们来装饰您的代码并帮助您查找错误。Support库本身也使用了这些注解,所以作为Support库的使用者,AndroidStudio已经根据这些注解验证了你的代码,并标记了潜在的问题。如何引入SupportAnnotations:默认不包含Annotations;它被打包为一个独立的库。如果使用了appcompat库,会自动导入SupportAnnotations,因为appcompat使用了SupportAnnotations。如果没有,它需要在构建中。在gradle中添加如下配置:dependencies{compile'c??om.android.support:support-annotations:23.4.0'}如果你引入了appcompatv7,可能不需要再重新引用support-annotations,因为appcompat包含了它的引用.支持注解类别:Typedef注解:IntDef/StringDef(Android特有的魔法变量注解替代Enum)EnuminAndroidEnumerationEnum是java中的一个完整类。而枚举中的每一个值都是枚举类中的一个对象。所以枚举的值在我们使用的时候会比整型常量消耗更多的内存。我们在Android应用中使用枚举的时候,如果我们的程序本身消耗内存比较大,或者是一个游戏应用。然后我们***使用常量而不是枚举。但是,改用常量后,就不能限制这个值了。那么最好的方法是什么?当然,Android支持注解库中有一些有用的注解助手。我们可以使用它们来解决我们之前的问题(在编译代码时)。IntDef和StringDef是两个神奇的变量注解。使用这两个替代了之前使用的Enum。它会帮助我们在编译时选择像Enum这样的变量的功能。@IntDef与“typedef”非常相似,你可以创建另一个注解,然后使用@IntDef来指定你期望的整数常量值列表,***你可以使用这个定义的注解来装饰你的API。接下来,让我们使用IntDef来替换Enum。publicclassMainActivityextendsActivity{publicstaticfinalintSUNDAY=0;publicstaticfinalintMONDAY=1;{...省略部分}@IntDef({SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY})@Retention(RetentionPolicy.SOURCE)public@interfaceWeekDays{}@WeekDaysintcurrentDay=SUNDAY;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);setCurrentDay(WEDNESDAY);@WeekDaysswintDay(get)CurrentDay(get)(今天){caseSUNDAY:break;caseMONDAY:break;{...省略}default:break;}}/***参数只能在声明范围内以整数传递,否则编译不通过*@paramcurrentDay*/publicvoidsetCurrentDay(@WeekDaysintcurrentDay){this.currentDay=currentDay;}@WeekDayspublicintgetCurrentDay(){returncurrentDay;}}说明:声明一些必要的int常量,声明一个注解为WeekDays,使用@IntDef修饰WeekDays,参数设置为要枚举的集合使用@保留(RetentionPolicy.SOURCE)指定注解只存在于源代码中,不添加到类文件中。调用时只能传入指定的类型。如果传入的类型不对,就会编译失败。我们还可以指定整数值作为标志,也就是说这些整数值可以使用'|'或'&'用于AND或操作。如果我们将@Flavour定义为如下标志:@IntDef(flag=true,value={SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY})public@interfaceFlavour{}那么我们可以这样调用它:setCurrentDay(周日和周三);@StringDef的用法与@IntDef基本相同,只是String类型不同。如何?使用起来还是很简单的。如果你只是冲着标题想办法替换Enum,看到这里可以直接跳到文末,点赞离开。如果你还想了解更多注解的强大功能,那就看下面的内容吧!Nullness注解@Nullable注解可以用来标识特定的参数或者返回值可以为null。@NonNull注释可用于标识参数不能为空。ResourceType注解资源在Android中作为整数值传递。这意味着期望获取一个drawable作为参数的代码很容易传递一个string类型的资源,因为它们的资源id都是整数,编译器很难区分。ResourceType注解可以提供这种情况下的类型检查,例如:如果类型指定错误,编译将不会通过。CommonResourceType注解用于指定整型参数、成员变量或方法来检查对应的资源类型。AnimatorRes:动画资源类型AnimRes:动画资源类型AnyRes:任意资源类型ArrayRes:数组资源类型AttrRes:attr资源类型BoolRes:布尔资源类型ColorRes:颜色资源类型DimenRes:dimen资源类型。DrawableRes:可绘制资源类型。FractionRes:分数资源类型IdRes:id资源类型IntegerRes:整数资源类型InterpolatorRes:插值器资源类型LayoutRes:布局资源类型MenuRes:菜单资源类型PluralsRes:复数资源类型RawRes:原始资源类型StringRes:字符串资源类型StyleableRes:可样式资源类型StyleRes:style资源类型TransitionRes:transition资源类型XmlRes:xml资源类型以上基本包含了所有的资源类型,但是有时候需要通过RGB颜色整数来设置颜色值,这时可以使用@ColorInt注解,意味着您期望的是表示颜色的整数值。如果使用不当,也会通过Threading注解编译失败。在指定线程中不执行就不能编译的几个Threading注解@UiThreadUI线程@MainThread主线程@WorkerThread子线程@BinderThread绑定线程ValueConstraints注解:@Size,@IntRange,@FloatRange在实际开发过程中,有时候我们可能需要设置一个取值范围,这时候我们可以使用取值范围注解来约束。比如我们设置一个百分比,取值范围为0-100。对于数据、集合和字符串,可以使用@Size注解参数来限制集合的大小(当参数为字符串时,可以限制字符串的长度)。举几个例子,集合不能为空:@Size(min=1)Thestring***canonlyhave23characters:@Size(max=23)Thearraycanonlyhave2elements:@Size(2)size的数组必须是2的倍数(比如图形API中位置的x/y坐标数组:@Size(multiple=2)Permissions注:@RequiresPermission有时候我们的方法调用需要调用者有指定的权限,那么我们可以使用@RequiresPermission注解,@RequiresPermission(Manifest.permission.SET_WALLPAPER)publicabstractvoidsetWallpaper(Bitmapbitmap)throwsIOException;除了上面的单一使用方法,官方还给出了以下使用场景(1)如果需要至少一个权限集,你可以使用anyOf属性@RequiresPermission(anyOf={Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION})publicabstractLocationgetLastKnownLocation(Stringprovider);(2)如果你同时需要多个权限ime,您可以使用allOf属性@RequiresPermission(allOf={Manifest.permission.READ_HISTORY_BOOKMARKS,Manifest.permission.WRITE_HISTORY_BOOKMARKS})publicstaticfinalvoidupdateVisitedHistory(ContentResolvercr,Stringurl,booleanreal);(3)对于intents的权限,可以直接在定义的intent常量字符串字段上标注权限要求(一般都有@SdkConstant注解标注)@RequiresPermission(android.Manifest.permission.BLUETOOTH)publicstaticfinalStringACTION_REQUEST_DISCOVERABLE="android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";(4)对于内容提供者的权限,可能需要单独标注读写权限,所以可以使用@Read或者@Write来标注每一个权限需求@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))@RequiresPermission。写(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))publicstaticfinalUriBOOKMARKS_URI=Uri.parse("content://browser/bookmarks");如果你的API允许使用SuperridingMethods:@Call或重写你的方法,但是,你需要在重写时调用你自己的方法(父方法)。这时候可以使用@CallSuper注解。例如:Activity的onCreate函数@CallSuperprotectedvoidonCreate(@NullableBundlesavedInstanceState)使用这个之后,当重写的方法没有调用父方法时,工具会给出一个标记提示ReturnValues注解:@CheckResult如果你的方法返回一个值而你期望调用者用这个值做一些事情,那么你可以使用@CheckResult注解来标记这个方法。这种方法在具体使用中很少用到,除非有特殊情况,比如在项目中处理一个数据。该处理是耗时的。我们希望调用函数的调用者不需要处理结果。不使用提示时,酌情删除调用。Keep注解Keep:指出一个方法在混淆时应该保留。在Android编译生成APK的过程中,我们通常需要将minifyEnabled设置为true,以达到以下两个效果:混淆代码,删除无用代码但出于某些目的,我们不需要混淆某些代码或不删除某些代码,在除了配置复杂的Proguard文件,我们还可以使用@Keep注解。@KeeppublicstaticintgetBitmapWidth(Bitmapbitmap){returnbitmap.getWidth();}其他注解VisibleForTesting:可以对类、方法或变量进行注解,以指示更宽松的可见性属性,使其具有更广泛的可见性,以便对代码进行测试。IntelliJannotationsdependencies{compile'c??om.intellij:annotations:12.0'}最后,通过查阅资料和博客,系统学习总结了SupportAnnotations注解的内容。通过在编码中使用SupportAnnotations,可以提高代码的可读性,同时可以在类加载时检查一些错误,对性能没有任何影响,因为SupportAnnotations中注解的生命周期都是RetentionPolicy。班级。您可以尝试在以后的编码中使用它。
