前言
使用注解需要用到上篇文章:https://mp.youkuaiyun.com/postedit/81352719 校验字符封装类
先贴使用代码:
data class AddUserInfo( @VCLevel(2) @VCRequired(stringName = "pleaseTypeInYourName") var name:String, @VCLevel(1) @VCRemoveSpace @VCRequired(stringName = "pleaseTypeInYourMsg") @VCMinLength(min = 6,stringName = "msgMinimumLength") @VCBetweenLength(min = 6,max = 18,stringName = "string_xml_name") @VCEqual(fieldName = "name",stringName = "string_xml_name") @VCMaxLength(max = 18,stringName = "string_xml_name") @VCMatches(regularExpression = "^[a-zA-Z]\\w{5,17}\$",stringName = "string_xml_name") var msg:String? )
stringName 是string.xml中的name
@VCLevel 级别, 最小值先判断
@VCRequired 必填
@VCRemoveSpace 移除空格
@VCMinLength 最小长度
@VCBetweenLength 之间
@VCEqual 判断值是否相等, fieldName 当前类的属性名称
@VCMaxLength 最大长度
@VCMatches 正则 , java1.8 环境下可对同个属性注解多次
有了这些, 基本上已经满足了项目中的需求。下面我贴上代码, 需要跟 上篇文章一起使用。
import android.content.Context import com.ml.lib_common.util.resValues.getStringId import java.lang.reflect.Field import java.lang.reflect.Type import java.util.* import kotlin.collections.ArrayList /** * 校验字符 注解 */ /** *是否移除空格 * level 校验的级别必须为0 */ @Target(AnnotationTarget.FIELD) @Retention(AnnotationRetention.RUNTIME) annotation class VCRemoveSpace(val value:Boolean = true,val level: Int = 0) /** *必填 *stringName=string.xml中的字符name(提示错误信息) *level 校验的级别大于0 */ @Target(AnnotationTarget.FIELD) @Retention(AnnotationRetention.RUNTIME) annotation class VCRequired(val stringName:String,val level: Int = 1) /** *最小长度 *stringName=string.xml 中的字符name(提示错误信息) *level 校验的级别大于0 */ @Target(AnnotationTarget.FIELD) @Retention(AnnotationRetention.RUNTIME) annotation class VCMinLength(val min:Int,val stringName:String,val level: Int = 2) /** *最大长度 *stringName=string.xml 中的字符name(提示错误信息) *level 校验的级别大于0 */ @Target(AnnotationTarget.FIELD) @Retention(AnnotationRetention.RUNTIME) annotation class VCMaxLength(val max:Int,val stringName:String,val level: Int = 2) /** *在 ... 之中 *stringName=string.xml 中的字符name(提示错误信息) *level 校验的级别大于0 */ @Target(AnnotationTarget.FIELD) @Retention(AnnotationRetention.RUNTIME) annotation class VCBetweenLength(val min:Int,val max:Int,val stringName:String,val level: Int = 2) /** *比较值是否相等 * fieldName = 本类要比较值的属性名称 * stringName=string.xml 中的字符name(提示错误信息) * level 校验的级别大于0 */ @Target(AnnotationTarget.FIELD) @Retention(AnnotationRetention.RUNTIME) annotation class VCEqual(val fieldName:String,val stringName:String,val level: Int = 2) /** *正则校验 * regularExpression = 正则表达式 * stringName=string.xml 中的字符name(提示错误信息) * level 校验的级别大于0 */ @Repeatable @Target(AnnotationTarget.FIELD) @Retention(AnnotationRetention.RUNTIME) annotation class VCMatches(val regularExpression:String,val stringName:String,val level: Int = 2) /** *校验级别,0最先校验 */ @Target(AnnotationTarget.FIELD) @Retention(AnnotationRetention.RUNTIME) annotation class VCLevel(val value:Int) private data class AnnotationLeveles(val level:Int,val annotations:Array<Annotation>,val fieldValue:Any?) private data class AnnotationLevel(val level:Int,val annotation:Annotation) /** * 执行校验注解 * context:上下文 * any:有注解的类 */ fun vcExecute(context: Context,any:Any):Boolean{ return vcExecute(context,any,false) } /** * 执行校验注解 * context:上下文 * any:有注解的类 * isRemoveSpace:是否去掉空格,当属性有 VCRemoveSpace注解时,会使用VCRemoveSpace的值 */ fun vcExecute(context: Context,any:Any,isRemoveSpace: Boolean):Boolean{ val verifyChar = VerifyChar() val jClass=any.javaClass //存放属性有VCLevel注解 val levelAnnotations = ArrayList<AnnotationLeveles>() //获取所有属性 jClass.declaredFields.forEach { field -> run { //获取属性上的注解 field.annotations.forEach { annotation -> run { if (annotation is VCLevel) {//找到级别注解 val annotationLeveles = AnnotationLeveles(annotation.value,field.annotations, getValueByFieldName(field,jClass,any)) levelAnnotations.add(annotationLeveles) return@forEach } } } } } //根据VCLevel注解,对所有属性上的注解排序 Collections.sort(levelAnnotations) { p0, p1 -> if(p0.level>p1.level){ return@sort 1 }else if(p0.level==p1.level){ return@sort 0 }else { return@sort -1 } } levelAnnotations.forEach { levelAnnotation -> run { //处理字符校验 if(levelAnnotation.fieldValue is String){ val levelAnnotations2 = ArrayList<AnnotationLevel>() levelAnnotation.annotations.forEach { //拿到每个属性的所有字符校验注解 when(it){ is VCRemoveSpace ->{ levelAnnotations2.add(AnnotationLevel(it.level,it)) } is VCRequired ->{ levelAnnotations2.add(AnnotationLevel(it.level,it)) } is VCMinLength ->{ levelAnnotations2.add(AnnotationLevel(it.level,it)) } is VCMaxLength ->{ levelAnnotations2.add(AnnotationLevel(it.level,it)) } is VCBetweenLength ->{ levelAnnotations2.add(AnnotationLevel(it.level,it)) } is VCEqual ->{ levelAnnotations2.add(AnnotationLevel(it.level,it)) } is VCMatches ->{ levelAnnotations2.add(AnnotationLevel(it.level,it)) } } } //根据注解的level值排序 Collections.sort(levelAnnotations2) { p0, p1 -> if(p0.level>p1.level){ return@sort 1 }else if(p0.level==p1.level){ return@sort 0 }else { return@sort -1 } } var fIsRemoveSpace:Boolean? = null //对排序后注解,进行处理 levelAnnotations2.forEach { when(it.annotation){ is VCRemoveSpace ->{ fIsRemoveSpace = it.annotation.value } is VCRequired ->{ verifyChar .with(levelAnnotation.fieldValue,fIsRemoveSpace?:isRemoveSpace) .required(getStringId(it.annotation.stringName)) } is VCMinLength ->{ verifyChar .with(levelAnnotation.fieldValue,fIsRemoveSpace?:isRemoveSpace) .minLength(it.annotation.min,getStringId(it.annotation.stringName)) } is VCMaxLength ->{ verifyChar .with(levelAnnotation.fieldValue,fIsRemoveSpace?:isRemoveSpace) .maxLength(it.annotation.max,getStringId(it.annotation.stringName)) } is VCBetweenLength ->{ verifyChar .with(levelAnnotation.fieldValue,fIsRemoveSpace?:isRemoveSpace) .betweenLength(it.annotation.min,it.annotation.max,getStringId(it.annotation.stringName)) } is VCEqual ->{ val v = getValueByFieldName(it.annotation.fieldName,jClass,any) if(v is String){ verifyChar .with(levelAnnotation.fieldValue,fIsRemoveSpace?:isRemoveSpace) .equal(v,getStringId(it.annotation.stringName)) }else{ verifyChar .with(levelAnnotation.fieldValue,fIsRemoveSpace?:isRemoveSpace) .equal(null,getStringId(it.annotation.stringName)) } } is VCMatches ->{ verifyChar .with(levelAnnotation.fieldValue,fIsRemoveSpace?:isRemoveSpace) .matches(it.annotation.regularExpression,getStringId(it.annotation.stringName)) } } if(!verifyChar.isValid){//有一次校验不通过了 return verifyChar.isValid(context)//结束此次校验 } } }else{//是否内部类中包含字符校验注解 levelAnnotation.fieldValue?.let { //内部类中, 有数据校验不通过,结束此次校验 if(!vcExecute(context,levelAnnotation.fieldValue,isRemoveSpace)){ return false } } } } } return true } /** * 得到属性的值 */ private fun getValueByFieldName(fieldName: String,jClass:Class<*>,ob:Any): Any? { try { return jClass.getField(fieldName).get(ob) }catch (e:IllegalAccessException){ // e.printStackTrace() //私用属性, 通过get方法获取值 val nameIndex0 = fieldName.subSequence(0,1).toString().toUpperCase() var nameIndexEnd = "" if(fieldName.length>1){ nameIndexEnd = fieldName.subSequence(1,fieldName.length).toString() } val methodGetName = "get$nameIndex0$nameIndexEnd" try { return jClass.getMethod(methodGetName).invoke(ob) }catch (e:UninitializedPropertyAccessException){ // e.printStackTrace() } } return null } /** * 得到属性的值,String为null时转换为"" */ private fun getValueByFieldName(field: Field,jClass:Class<*>,ob:Any): Any? { val name = field.name try { return toNullString(field.genericType,field.get(ob)) }catch (e:IllegalAccessException){ // e.printStackTrace() //私用属性, 通过get方法获取值 val nameIndex0 = name.subSequence(0,1).toString().toUpperCase() var nameIndexEnd = "" if(name.length>1){ nameIndexEnd = name.subSequence(1,name.length).toString() } val methodGetName = "get$nameIndex0$nameIndexEnd" try { return toNullString(field.genericType,jClass.getMethod(methodGetName).invoke(ob)) }catch (e:UninitializedPropertyAccessException){ // e.printStackTrace() } } return toNullString(field.genericType,null) } /** * 把string null 转为 "" */ private fun toNullString(genericType: Type,any :Any?):Any?{ if(any==null){ return if ("class java.lang.String"==genericType.toString()){ "" }else{ null } } return any }
祝大家, 生活愉快~。~