Android|Android Form组件

场景
Android APP里面时常有于登录、注册、信息填写提交等页面,业务逻辑差不多都是用户输入或者选择某些信息,然后点击提交,客户端这边依次判断用户名是否为空,长度是否在某个范围内等等,如果某一个不符合要求,就提示相应信息,如果都符合,就组合成key=value形式发起请求。
引申
上述场景类似于HTML里面的form标签

First name:
Last name:
复制代码

在Android里面,登录、注册这些页面是否也像一个个form呢,我们能否也用一个配置文件配置请求的URL,请求方式,然后配置相关的控件,最后在点击提交按钮时自动组装?
【Android|Android Form组件】再引申一步,登录页面里面,我们需要判断用户名为空、长度、匹配规则等,密码为空、长度、匹配规则等,然后分别给提示。在信息填写页面就更多了,有可能需要用户输入好几十条的信息分别判断,这样就导致了代码冗余和重复。能否在配置里面就配置好相应的检查规则,在点击提交的时候自动依次检查?
答案是可以的~下面就来看看例子
示例布局



为了简单快捷,都是用的LinearLayout,这样影响性能,这里当一个反面教材吧。。。
常规写法
  1. 先findByID,获取全部的控件。
  2. 按钮设置监听。
  3. 按钮点击之后依次判断:性别是否选择?没有就提示;账号是否为空?长度是否是11位?没有分别弹提示;密码是否为空?长度是否大于6?长度是否小于16?没有分别弹提示;协议编号是否为空?是否都是字母?没有弹提示。
  4. 如果还有其他信息,依次增加同样的逻辑。
封装之后
json配置
{ "action":"https://www.xxx.com", "method":"post", "item":[ { "id":"rg_sex", "rules":{ "notNull":[true, "性别不能为空"] }, "paramName":"sex" }, { "id":"et_user", "rules":{ "notNull":[true, "账号不能为空"], "length":[11, "账号长度必须是11位"] }, "paramName":"userName" }, { "id":"et_password", "rules":{ "notNull":[true, "密码不能为空"], "minLength":[6, "密码最短为6位"], "maxLength":[16, "密码最长为16位"] }, "paramName":"userPwd" }, { "id":"diy_view", "rules":{ "notNull":[true, "协议编号不能为空"], "textMatch":["[a-zA-Z]+", "协议编号需要全部为字母"] }, "paramName":"protocol" }, { "id":"btn_login", "type":"submit" } ] } 复制代码

action:提交的URL
method:提交的方式
item:Form里面的控件,比如选择按钮、文本框和提交按钮等。
id:控件定义的id,使用反射获取控件。
rules:检测规则,比如不为空、长度检查等。点击提交时会按照里面配置的规则依次检查。
paramName:点击提交时,对应的key。value就是控件里面的内容。
type代表控件类型,无此字段时,则默认需要获取该控件内容上传,如果为“submit”,则表示是个提交按钮,当点击该按钮时,会逐个检查其他字段是否匹配规则,如果都通过了,则会组装全部参数返回。
程序代码
// 自定义View,里面绘制了文字 DIYView diyView = findViewById(R.id.diy_view); diyView.setText("abxcSDDFsdcAd"); // 自定义规则,名称是“textmatch”,类名是RuleTextMatch.java Form.addRule("textMatch", RuleTextMatch.class); // 自定义检查的View,用于检查DIYView等其他View的输入,可通过instanceof判断类型之后获取相应内容 Form.setCheckView(DIYCheckView.class); String jsonStr = FileUtil.parseAssetsFile(this, "config/testConfig01.json"); Form form = new Form(); form.parseView(view, jsonStr); form.setFormCommitListener(new OnFormCommitListener() { @Override public void onFormCommitChecked(Form form, String method, String url, Map paramMap) { Toast.makeText(MainActivity.this, "method=" + method + "\nurl=" + url + "\n" + "paramMap=" + paramMap.toString(), Toast.LENGTH_SHORT).show(); }@Override public void onFormCommitError(Form form, ICheckItem checkItem, IRule errorRule) { Toast.makeText(MainActivity.this, errorRule.getErrorMsg(), Toast.LENGTH_SHORT).show(); } }); 复制代码

说明 由于json配置文件里面写明了id,所以库里面就自动findViewByID了,外部调用省去了该过程。rules写明了判断规则,第一个参数是条件,第二个参数默认是未符合的情况下的提示,当然,这个在实现了IRule接口之后可以自己定义参数的顺序和含义。rules里面的顺序决定了程序判断的顺序。
扩展
扩展规则 例如扩展一个正则匹配的规则,名称是“textMatch”。
  1. 新建一个类RuleTextMatch继承AbsRule,或者实现IRule接口。
public class RuleTextMatch extends AbsRule {private String matchFormatStr = null; @Override public void setParam(List paramList) { super.setParam(paramList); if (paramList != null && paramList.size() > 0) { Object item = paramList.get(0); if (item instanceof String) { matchFormatStr = (String) item; } } }@Override public boolean check(ICheckItem checkItem) { if (TextUtils.isEmpty(matchFormatStr)) { return true; } String content = checkItem.getCheckContent(); if (content == null) { return false; } Pattern pattern = Pattern.compile(matchFormatStr); Matcher matcher = pattern.matcher(content); return matcher.matches(); } } 复制代码
  1. 注册该规则
//在程序启动的时候就可以注册了,使用Form的静态方法addRule Form.addRule("textMatch", RuleTextMatch.class); 复制代码

  1. json配置
{ "id":"diy_view", "rules":{ "notNull":[true, "协议编号不能为空"], "textMatch":["[a-zA-Z]+", "协议编号需要全部为字母"] }, "paramName":"protocol" } 复制代码

扩展View 目前阶段只支持RadioGroup和TextView(EditText, Button等继承了TextView),如果想扩展其他的View,只需要创建一个类继承CheckView或者实现ICheckItem接口即可。 例如我们自定义了一个DIYView。
  1. DIYView
public class DIYView extends View { // ...省略其他方法 private String text; public String getText() { return text; } // ...省略其他方法 } 复制代码

  1. 需要扩展一个类DIYCheckView,来解析DIYView和其他扩展的View。整个外部扩展解析类只需要这一个就可以了。
public class DIYCheckView extends CheckView {@Override public String getCheckContent() { String content = super.getCheckContent(); if (content != null) { return content; } // 通过instanceof判断各个类型View的获取文本的方法。 if (view instanceof DIYView) { return ((DIYView) view).getText(); } return content; } } 复制代码

  1. 使用
// 在程序启动时,调用Form的静态方法setCheckView就可以了 Form.setCheckView(DIYCheckView.class); 复制代码

小结
  1. 文中的输入信息的就三四个,可能觉得自己写也挺快。但是如果需要用户填写详细信息好几十条的时候,每个都要判断一些乱七八糟的规则,这个就轻松多了。
  2. 由于加载的是配置文件,也就是说该文件是可以随时更新的,当某一个规则发生变化的时候可以及时更新,例如本地判断了用户名11位,后来需求更改不限制位数了,只需要更新配置文件即可。
  3. 由于是一个aar库,不用每次去编译,扩展的时候也不需要修改库里面的文件。
现阶段处于起始阶段,支持的规则和判断的View比较少,后续会增加,链接如下,希望大家不腻赐教,谢谢!
git链接:FormLike 转载于:https://juejin.im/post/5b56977df265da0f990d5c2e

    推荐阅读