Android 表单逻辑校验方案的探讨
一、需求
如图,一个简单的表单页面,本文只讨论提交表单时的逻辑校验。
二、以前的写法
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
private EditText mTvUserName;
private EditText mTvPassword;
private TextView mTvLogin;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mTvUserName = (EditText) findViewById(R.id.tv_username);
mTvPassword = (EditText) findViewById(R.id.tv_password);
mTvLogin = (TextView) findViewById(R.id.tv_login);
mTvLogin.setOnClickListener(this);
}
@Override
public void onClick(View v) {
String userName = getViewContent(mTvUserName);
String password = getViewContent(mTvPassword);
if (TextUtils.isEmpty(userName)) {
showToast("请输入用户名");
return;
}
if (TextUtils.isEmpty(password)) {
showToast("请输入密码");
return;
}
login();
}
private void login() {
// TODO 调用登录请求
}
private String getViewContent(View view) {
return view.getText().toString().trim();
}
private void showToast(String tip) {
Toast.makeText(this, tip, Toast.LENGTH_SHORT).show();
}
}
关键看onClick(View v)
方法内部的校验,由于当前的校验只有两个,代码相对简单;
三、需求升级
用户名必须为手机号,新增出生日期、年龄等校验逻辑;
代码如下:
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
private EditText mTvUserName;
private EditText mTvPassword;
private EditText mTvBirthday;
private EditText mTvAge;
private TextView mTvLogin;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mTvUserName = (EditText) findViewById(R.id.tv_username);
mTvPassword = (EditText) findViewById(R.id.tv_password);
mTvBirthday= (EditText) findViewById(R.id.tv_birthday);
mTvAge= (EditText) findViewById(R.id.tv_age);
mTvLogin = (TextView) findViewById(R.id.tv_login);
mTvLogin.setOnClickListener(this);
}
@Override
public void onClick(View v) {
String userName = getViewContent(mTvUserName);
String password = getViewContent(mTvPassword);
String birthday= getViewContent(mTvBirthday);
String age = getViewContent(mTvAge);
if (TextUtils.isEmpty(userName)) {
showToast("请输入用户名");
return;
}
if (RegUtil.isPhone(userName)) {
showToast("请输入正确的手机号");
return;
}
if (TextUtils.isEmpty(password)) {
showToast("请输入密码");
return;
}
if (TextUtils.isEmpty(birthday)) {
showToast("请输入出生日期");
return;
}
if (TextUtils.isEmpty(age)) {
showToast("请输入年龄");
return;
}
login();
}
...省略代码...
}
可以看到onClick(View v)
方法中代码爆炸式增长;
四、解决方案:通过异常去处理逻辑
- 需要自定义一个业务异常类
- 需要一个统一的业务校验类
- 页面逻辑修改
4.1 业务异常类
public class BizRunningException extends RuntimeException {
private static final String DEFAULT_ERROR_CODE = "UNKNOW_ERROR";
private String errorCode = DEFAULT_ERROR_CODE;
private String errorMsg = null;
public BizRunningException(String message) {
super(message);
this.errorMsg = message;
}
public BizRunningException(String code, String message) {
super(message);
this.errorCode = code;
this.errorMsg = message;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorCode() {
return this.errorCode;
}
public String getErrorMsg() {
if (errorMsg != null) {
return errorMsg;
}
return DEFAULT_ERROR_CODE;
}
}
4.2 业务校验类
public class ComLogicUtil {
public static String getViewContent(TextView view) {
return view.getText().toString().trim();
}
/**
* 获取控件中的文本内容
* @param view:指定的控件
* @param msg:控件内容为空时,提示的内容
* @return
* @throws BizRunningException
*/
public static String getViewContent(TextView view, String msg) throws BizRunningException {
String content = getViewContent(view);
if (GenericUtil.isEmpty(content)) {
throw new BizRunningException(msg);
}
return content;
}
public static String getViewContent(TextView view, @StringRes int msgId) throws BizRunningException {
return getViewContent(view, view.getContext().getString(msgId));
}
//**************** 校验数据 *************
public static String checkString(String str, String msg) throws BizRunningException {
if (str == null || GenericUtil.isEmpty(str.trim())) {
throw new BizRunningException(msg);
}
return str;
}
/**
* 根据给定的flag,判断是否要抛出异常
* @param flag
* @param msg
* @throws BizRunningException
*/
public static void checkByFlag(boolean flag, String msg) throws BizRunningException {
if (flag) {
throw new BizRunningException(msg);
}
}
}
4.3 页面逻辑修改
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
private EditText mTvUserName;
private EditText mTvPassword;
private EditText mTvBirthday;
private EditText mTvAge;
private TextView mTvLogin;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mTvUserName = (EditText) findViewById(R.id.tv_username);
mTvPassword = (EditText) findViewById(R.id.tv_password);
mTvBirthday= (EditText) findViewById(R.id.tv_birthday);
mTvAge= (EditText) findViewById(R.id.tv_age);
mTvLogin = (TextView) findViewById(R.id.tv_login);
mTvLogin.setOnClickListener(this);
}
@Override
public void onClick(View v) {
try {
String userName = ComLogicUtil.getViewContent(mTvUserName, "请输入用户名");
ComLogicUtil.checkByFlag(!RegUtil.isPhone(userName), "请输入正确的手机号");
String password = ComLogicUtil.getViewContent(mTvPassword, "请输入密码");
String birthday= ComLogicUtil.getViewContent(mTvBirthday, "请输入出生日期");
String age = ComLogicUtil.getViewContent(mTvAge, "请输入年龄");
login();
} catch (BizRunningException e) {
showToast(e.getErrorMsg());
}
}
...省略代码...
}
现在,所有条件的逻辑校验都是一行解决;