Android APP里面时常有于登陆、注册、信息填写提交等页面,业务逻辑差很少都是用户输入或者选择某些信息,而后点击提交,客户端这边依次判断用户名是否为空,长度是否在某个范围内等等,若是某一个不符合要求,就提示相应信息,若是都符合,就组合成key=value形式发起请求。php
上述场景相似于HTML里面的form标签html
<form action="form_action.asp" method="get">
<p>First name: <input type="text" name="fname" /></p>
<p>Last name: <input type="text" name="lname" /></p>
<input type="submit" value="Submit" />
</form>
复制代码
在Android里面,登陆、注册这些页面是否也像一个个form呢,咱们可否也用一个配置文件配置请求的URL,请求方式,而后配置相关的控件,最后在点击提交按钮时自动组装?java
再引伸一步,登陆页面里面,咱们须要判断用户名为空、长度、匹配规则等,密码为空、长度、匹配规则等,而后分别给提示。在信息填写页面就更多了,有可能须要用户输入好几十条的信息分别判断,这样就致使了代码冗余和重复。可否在配置里面就配置好相应的检查规则,在点击提交的时候自动依次检查?android
答案是能够的~下面就来看看例子git
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="20dp">
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" >
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/chose_sex" />
<RadioGroup android:id="@+id/rg_sex" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" >
<RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/sex_male" />
<RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/sex_female" />
</RadioGroup>
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" android:layout_marginTop="10dp" >
<ImageView android:layout_width="25dp" android:layout_height="25dp" android:src="@mipmap/user" />
<EditText android:id="@+id/et_user" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/et_name_hint" android:layout_marginLeft="10dp" android:inputType="number" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" android:layout_marginTop="10dp" >
<ImageView android:layout_width="25dp" android:layout_height="25dp" android:src="@mipmap/password" />
<EditText android:id="@+id/et_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/et_password_hint" android:layout_marginLeft="10dp" android:inputType="textPassword" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" android:layout_marginTop="10dp" >
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/protocol_num" />
<com.kongge.formlikedemo.view.DIYView android:id="@+id/diy_view" android:layout_width="match_parent" android:layout_height="30dp" android:layout_marginLeft="10dp" />
</LinearLayout>
<Button android:id="@+id/btn_login" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/login_btn_bg" android:text="@string/btn_login" android:layout_marginTop="10dp" />
</LinearLayout>
复制代码
为了简单快捷,都是用的LinearLayout,这样影响性能,这里当一个反面教材吧。。。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:提交的URLbash
method:提交的方式ide
item:Form里面的控件,好比选择按钮、文本框和提交按钮等。布局
id:控件定义的id,使用反射获取控件。post
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<String, String> 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”。
public class RuleTextMatch extends AbsRule {
private String matchFormatStr = null;
@Override
public void setParam(List<Object> 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();
}
}
复制代码
//在程序启动的时候就能够注册了,使用Form的静态方法addRule
Form.addRule("textMatch", RuleTextMatch.class);
复制代码
{
"id":"diy_view",
"rules":{
"notNull":[true, "协议编号不能为空"],
"textMatch":["[a-zA-Z]+", "协议编号须要所有为字母"]
},
"paramName":"protocol"
}
复制代码
目前阶段只支持RadioGroup和TextView(EditText, Button等继承了TextView),若是想扩展其余的View,只须要建立一个类继承CheckView或者实现ICheckItem接口便可。 例如咱们自定义了一个DIYView。
public class DIYView extends View {
// ...省略其余方法
private String text;
public String getText() {
return text;
}
// ...省略其余方法
}
复制代码
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;
}
}
复制代码
// 在程序启动时,调用Form的静态方法setCheckView就能够了
Form.setCheckView(DIYCheckView.class);
复制代码
现阶段处于起始阶段,支持的规则和判断的View比较少,后续会增长,连接以下,但愿你们不腻赐教,谢谢!