Android注解方式实现表单校验
在开发中总会遇到输入框的输入规则限制
比如 电话输入框电话号码的校验,密码规则的校验等 ,我们通常做法是提交操作时对每个输入框的输入内容进行校验,很多的if else ,代码看起来很乱,其实我们可以用反射注解的方式去声明一些判断规则这样会更好,代码可读性更强。
java反射文章推荐:http://www.jianshu.com/p/5b3acad0f025
下面我们通过一个例子去讲解注解方式去实现表达式的校验
这个包下定义的是注解实体类,每一个类都是一个注解规则,如Index类代码:
这个包下都是一些javabean, 如AttrBean代码:
BaseBean基础类,每个bean是一个规则javabean类,
结果回调类
处理回调校验结果
上面主要是校验器和工具类:
public class ValidateUtil { /**
* 设置校验view的信息
* @param view
* @param isEditText
* @param msg
* @param validateResult
*/
private static void setViewInfo(Object view, boolean isEditText, String msg, IValidateResult validateResult) {
if (isEditText) {
validateResult.onValidateError(msg, ((EditText) view));
} else {
validateResult.onValidateError(msg, null);
}
} /**
* 不可为空
* @param view
* @param isEt
* @param msg
* @param validateResult
* @return
*/
public static boolean notNull(Object view, boolean isEt, String msg, IValidateResult validateResult) {
if (TextUtils.isEmpty(((TextView) view).getText().toString())) {
setViewInfo(view, isEt, msg, validateResult);
return true;
}
return false;
} /**
* 判断是否为空
* @param view
* @return
*/
public static boolean isNull(Object view) {
if (view == null)
throw new NullPointerException("view can not be null");
if (TextUtils.isEmpty(((TextView) view).getText().toString())) {
return true;
}
return false;
} /**
* 根据正则表达式校验
* @param view
* @param isEt
* @param bean
* @param validateResult
* @return
*/
public static boolean checkPattern(Object view, boolean isEt, PatternBean bean, IValidateResult validateResult) {
if (isNull(view)) return true; Pattern r = Pattern.compile(bean.pattern);
Matcher m = r.matcher(((TextView) view).getText().toString());
if (!m.matches()) {
setViewInfo(view, isEt, bean.msg, validateResult);
return true;
}
return false;
} /**
* 最大长度校验
* @param view
* @param isEt
* @param bean
* @param validateResult
* @return
*/
public static boolean maxLenght(Object view, boolean isEt, LengthBean bean, IValidateResult validateResult) {
if (isNull(view)) return true; if (((TextView) view).getText().toString().length() > bean.length) {
setViewInfo(view, isEt, bean.msg, validateResult);
return true;
}
return false;
}
}
public class ValidateManager {
private static final String TAG = "ValidateManager";
/**
* 注册的页面
*/
private static Map<Object, List<AttrBean>> registList = new HashMap<>();
/**
* 类型
*/
private static final String TYPE_NOTNULL = "NotNull";
private static final String TYPE_PATTERN = "PATTERN";
private static final String TYPE_MAXLENGTH = "MAXLENGTH";
private static final String TYPE_MINLENGTH = "MINLENGTH";
private static final String TYPE_PASSWORDFIRST = "PASSWORD_FIRST";
private static final String TYPE_PASSWORDSECOND = "PASSWORD_SECOND";
private static final String TYPE_SKIP = "SKIP"; public static void check(Object activity, boolean isSkip, IValidateResult validateResult) {
if (activity == null || validateResult == null) return;
List<AttrBean> list = registList.get(activity);
if (list == null) return;
for (AttrBean attrBean : list) {
if (attrBean.index == null) {
return;
}
}
Collections.sort(list, new Comparator<AttrBean>() {
public int compare(AttrBean arg0, AttrBean arg1) {
return arg0.index.compareTo(arg1.index);
}
});
for (AttrBean attrBean : list) {
for (Basebean bean : attrBean.annos) {
if (isSkip) {
if (TYPE_SKIP.equals(attrBean.annos.getLast().type)) {
break;
}
}
if (TYPE_NOTNULL.equals(bean.type)) {
if (ValidateUtil.notNull(attrBean.view, attrBean.isEditText, bean.msg, validateResult)) {
return;
}
} else if (TYPE_PATTERN.equals(bean.type)) {
if (ValidateUtil.checkPattern(attrBean.view, attrBean.isEditText, (PatternBean) bean, validateResult)) {
return;
}
} else if (TYPE_MAXLENGTH.equals(bean.type)) {
if (ValidateUtil.maxLenght(attrBean.view, attrBean.isEditText, (LengthBean) bean, validateResult)) {
return;
}
} else if (TYPE_MINLENGTH.equals(bean.type)) {
if (ValidateUtil.minLenght(attrBean.view, attrBean.isEditText, (LengthBean) bean, validateResult)) {
return;
}
} else if (TYPE_PASSWORDFIRST.equals(bean.type)) {
if (ValidateUtil.isNull(attrBean.view)) {
return;
}
pwd1Attr = attrBean;
} else if (TYPE_PASSWORDSECOND.equals(bean.type)) {
if (ValidateUtil.password(attrBean, pwd1Attr, (PasswordBean) bean, validateResult)) {
return;
}
pwd1Attr = null;
}
}
}
validateResult.onValidateSuccess();
pwd1Attr = null;
} private static AttrBean pwd1Attr = null; private static class ValidateRegRunnable implements Runnable {
Object target; public ValidateRegRunnable(Object target) {
this.target = target;
} @Override
public void run() {
try {
Class clazz = target.getClass(); for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(NotNull.class) ||
field.isAnnotationPresent(Pattern.class) ||
field.isAnnotationPresent(MaxLength.class) ||
field.isAnnotationPresent(MinLength.class) ||
field.isAnnotationPresent(Index.class) ||
field.isAnnotationPresent(PasswordFirst.class) ||
field.isAnnotationPresent(PasswordSecond.class)) { if (field.getType() != EditText.class) {
throw new RuntimeException("annotation must be on the EditText");
}
field.setAccessible(true);
List<AttrBean> editTextMap = registList.get(target);
if (editTextMap == null) {
editTextMap = new LinkedList<>();
registList.put(target, editTextMap);
}
AttrBean attr = new AttrBean();
attr.name = field.getName();
attr.view = field.get(target); if (field.getType() == EditText.class) {
attr.isEditText = true;
} else if (field.getType() == TextView.class) {
attr.isEditText = false;
}
if (attr.annos == null) {
attr.annos = new LinkedList<>();
}
editTextMap.add(attr); if (field.isAnnotationPresent(NotNull.class))
attr.annos.add(validateType(field, TYPE_NOTNULL));
if (field.isAnnotationPresent(Pattern.class))
attr.annos.add(validateType(field, TYPE_PATTERN));
if (field.isAnnotationPresent(MaxLength.class)) {
attr.annos.add(validateType(field, TYPE_MAXLENGTH));
if (attr.view != null && attr.isEditText) {
int length = field.getAnnotation(MaxLength.class).length();
((EditText) attr.view).setFilters(new InputFilter[]{new InputFilter.LengthFilter(length)});
}
}
if (field.isAnnotationPresent(MinLength.class))
attr.annos.add(validateType(field, TYPE_MINLENGTH));
if (field.isAnnotationPresent(PasswordFirst.class)) {
attr.annos.add(validateType(field, TYPE_PASSWORDFIRST));
if (attr.view != null && attr.isEditText) {
((EditText) attr.view).setTransformationMethod(PasswordTransformationMethod.getInstance());
}
}
if (field.isAnnotationPresent(PasswordSecond.class)) {
attr.annos.add(validateType(field, TYPE_PASSWORDSECOND));
if (attr.view != null && attr.isEditText) {
((EditText) attr.view).setTransformationMethod(PasswordTransformationMethod.getInstance());
}
}
if (field.isAnnotationPresent(Index.class))
attr.index = field.getAnnotation(Index.class).value();
if (field.isAnnotationPresent(Skip.class))
attr.annos.add(validateType(field, TYPE_SKIP));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
} /**
* 根据不同类型校验
* @param field
* @param type
* @return
* @throws IllegalAccessException
*/
private static Basebean validateType(Field field, String type) throws IllegalAccessException {
if (type.equals(TYPE_NOTNULL)) {
NotNull notnull = field.getAnnotation(NotNull.class);
NotNullBean bean = new NotNullBean();
bean.msg = notnull.msg();
bean.type = type;
return bean;
} else if (type.equals(TYPE_PATTERN)) {
Pattern re = field.getAnnotation(Pattern.class);
PatternBean reBean = new PatternBean();
reBean.msg = re.msg();
reBean.type = TYPE_PATTERN;
reBean.pattern = re.pattern();
return reBean;
} else if (type.equals(TYPE_MAXLENGTH)) {
MaxLength anno = field.getAnnotation(MaxLength.class);
LengthBean bean = new LengthBean();
bean.msg = anno.msg();
bean.type = TYPE_MAXLENGTH;
bean.length = anno.length();
return bean;
} else if (type.equals(TYPE_MINLENGTH)) {
MinLength anno = field.getAnnotation(MinLength.class);
LengthBean bean = new LengthBean();
bean.msg = anno.msg();
bean.type = TYPE_MINLENGTH;
bean.length = anno.length();
return bean;
} else if (type.equals(TYPE_PASSWORDFIRST)) {
PasswordBean bean = new PasswordBean();
bean.type = TYPE_PASSWORDFIRST;
return bean;
} else if (type.equals(TYPE_PASSWORDSECOND)) {
PasswordSecond anno = field.getAnnotation(PasswordSecond.class);
PasswordBean bean = new PasswordBean();
bean.msg = anno.msg();
bean.type = TYPE_PASSWORDSECOND;
return bean;
} else if (type.equals(TYPE_SKIP)) {
Basebean bean = new Basebean();
bean.type = TYPE_SKIP;
return bean;
} return null;
} /**
* 注册
* @param target
*/
public static void regist(final Object target) {
new Thread(new ValidateRegRunnable(target)).start();
} /**
* 解注册
* @param target
*/
public static void unregist(Object target) {
registList.remove(target);
}
}
我只贴出了部分代码,可以根据项目实际需求去添加规则,再把相应的校验器代码扩展到这个类里。
我们在主页面使用 按照正常的注解方式去实现 如下:
index是校验的顺序,需要正则表达式校验的输入框我们通过pattern去通过正则表达式去实现,minLength和maxLength是最小最大长度校验
完成后调用ValidateManager.check(this , isSkip , this);实现校验功能,经过回调处理(isSkip是否可以忽略不校验此项)
可以对指定输入框的view进行错误提醒,比如上面 对输入框背景色设置红色等操作。需源码的留邮箱。
Android注解方式实现表单校验的更多相关文章
- ng-messages AngularJs 表单校验方式
最新研究了一下表单校验,直接上代码. <!DOCTYPE html><html ng-app='app'><head> <meta charset=" ...
- 【JAVAWEB学习笔记】28_jqueryAjax:json数据结构、jquery的ajax操作和表单校验插件
Ajax-jqueryAjax 今天内容: 1.json数据结构(重点) 2.jquery的ajax操作(重点) 3.jquery的插件使用 一.json数据结构 1.什么是json JSON(J ...
- 测试开发【提测平台】分享10-Element UI抽屉和表单校验&增改接口合并实现应用管理
微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 开篇说个小讨论,一个群里聊天聊到关于更新篇章的长度,是小篇幅多次,还是每次按照一个小完整的功能,我个人的是按照后种来的,主要的思考就是希望 ...
- Spring MVC 文件上传、Restful、表单校验框架
目录 文件上传 Restful Restful 简介 Rest 行为常用约定方式 Restful开发入门 表单校验框架 表单校验框架介绍 快速入门 多规则校验 嵌套校验 分组校验 综合案例 实用校验范 ...
- 利用jquery.validate以及bootstrap的tooltip开发气泡式的表单校验组件
表单校验是页面开发中非常常见的一类需求,相信每个前端开发人员都有这方面的经验.网上有很多成熟的表单校验框架,虽然按照它们默认的设计,用起来没有多大的问题,但是在实际工作中,表单校验有可能有比较复杂的个 ...
- angularJs表单校验(超级详细!!!)
html代码 <!DOCTYPE html> <html ng-app="angularFormCheckModule"> <head> < ...
- 表单校验组件ValidForm
10.1使用入门 1.引入css 请查看下载文件中的style.css,把里面Validform必须部分复制到你的css中 (文件里这个注释 "/*==========以下部分是Validf ...
- JEECG 3.7.8 新版表单校验提示风格使用&升级方法(validform 新风格漂亮,布局简单)
JEECG 表单校验采用的是validform,默认的校验提示需要占用页面布局,提示效果较传统.jeecg这个自定义的校验提示风格,不占用页面布局,提示效果也更美观,简单易用,让表单看起来更漂亮!!! ...
- easyui 进阶之表单校验、自定义校验
前言 easyui是一种基于jQuery的用户界面插件集合,它为创建现代化,互动,JavaScript应用程序,提供必要的功能,完美支持HTML5网页的完整框架,节省网页开发的时间和规模.非常的简单易 ...
随机推荐
- [转载]ACM搜索算法总结(总结)
原文地址:ACM搜索算法总结(总结)作者:GreenHand 搜索是ACM竞赛中的常见算法,本文的主要内容就是分析它的 特点,以及在实际问题中如何合理的选择搜索方法,提高效率.文章的第一部分首先分析了 ...
- setup 命令中防火墙配置选项无法打开
故障提示 1.1 如何让setup 命令中防火墙配置生效 1.1.1 CentOS系统找不到setup命令工具的解决方法 yum -y install setuptool #安装setup命令工具 y ...
- JavaScript变量存储浅析
var test=100; function foo(){ console.log(test);//undefined var test=200; console.log(test); } 我们明明定 ...
- 粗略整理的java面试题
1.垃圾回收 是回收的空闲堆空间 只有在cpu空闲并且堆空间不足的情况下才回收 2.threadlocal 就是为线程的变量都提供了一个副本,每个线程运行都只是在更新这个副本. Threadloc ...
- SqlServer 数据库附加问题:不是主数据库文件
一.前言 今天公司要切换数据库服务器,数据库文件大于2G,结果再附加到另一服务器的数据库里面,就产生了一个问题.如下: 标题:Microsoft SQL Server Management Studi ...
- selenium-iframe操作
iframe,又叫浮动帧标记,是内嵌的网页元素,可以将一个html文件嵌入到另一个html文件中显示. 最典型的案例就是163邮箱登录:http://mail.163.com/,被绿色覆盖的部分即为i ...
- C语言 第三章 关系、逻辑运算与分支流程控制
目录 一.关系运算 二.逻辑运算 三.运算优先级 四.if语句 4.0.代码块 4.1.单if语句 4.2.if else 4.3.多重if 4.4.?号:号表达式 五.switch语句 一.关系运算 ...
- Leetcode刷题
Leetcode题库 本博客用于记录在LeetCode网站上一些题的解答方法.具体实现方法纯属个人的一些解答,这些解答可能不是好的解答方法,记录在此,督促自己多学习多练习. The ...
- HDnoip2017题解
那么,作为一名初入信息竞赛的选手,我也试着开始用博客记录自己的学习历程,那么这篇文章先简单介绍一下我自己吧. 本人开始学习信息学大概以来,主要都是用的C++,所以对其他语言并不是十分熟悉.2016我还 ...
- java 之 简单工厂模式(大话设计模式)
以前只是看设计模式,每次看完都去理解一次,并没有手动去写代码,所以理解的还不是很深刻,最近查看框架源码,发现很多地方用到的都是设计模式,因为对设计模式理解的不够深刻,所以源码查看进度很慢!现在决定来温 ...