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比較少,後續會增長,連接以下,但願你們不膩賜教,謝謝!