核心层的逻辑
核心层处于接口层和界面层之间,向下调用Api,向上提供Action,它的核心任务就是处理复杂的业务逻辑。先看看我对Action的定义:
public interface AppAction {
// 发送手机验证码
public void sendSmsCode(String phoneNum, ActionCallbackListener<Void> listener);
// 注册
public void register(String phoneNum, String code, String password, ActionCallbackListener<Void> listener);
// 登录
public void login(String loginName, String password, ActionCallbackListener<Void> listener);
// 按分页获取券列表
public void listCoupon(int currentPage, ActionCallbackListener<List<CouponBO>> listener);
}
首先,和Api接口对比就会发现,参数并不一致。登录并没有iemi和loginOS的参数,获取券列表的参数里也少了pageSize。这是因为,这几个参数,跟界面其实并没有直接关系。Action只要定义好跟界面相关的就可以了,其他需要的参数,在具体实现时再去获取。 另外,大部分action的处理都是异步的,因此,添加了回调监听器ActionCallbackListener,回调监听器的泛型则是返回的对象数据类型,例如获取券列表,返回的数据类型就是List,没有对象数据时则为Void。回调监听器只定义了成功和失败的方法,如下:
public interface ActionCallbackListener<T> {
/**
* 成功时调用
*
* @param data 返回的数据
*/
public void onSuccess(T data);
/**
* 失败时调用
*
* @param errorEvemt 错误码
* @param message 错误信息
*/
public void onFailure(String errorEvent, String message);
}
接下来再看看Action的实现。首先,要获取imei,那就需要传入一个Context;另外,还需要loginOS和pageSize,这定义为常量就可以了;还有,要调用接口层,所以还需要Api实例。而接口的实现分为两步,第一步做参数检查,第二步用异步任务调用Api。具体实现如下:
public class AppActionImpl implements AppAction {
private final static int LOGIN_OS = 1; // 表示Android
private final static int PAGE_SIZE = 20; // 默认每页20条
private Context context;
private Api api;
public AppActionImpl(Context context) {
this.context = context;
this.api = new ApiImpl();
}
@Override
public void sendSmsCode(final String phoneNum, final ActionCallbackListener<Void> listener) {
// 参数为空检查
if (TextUtils.isEmpty(phoneNum)) {
if (listener != null) {
listener.onFailure(ErrorEvent.PARAM_NULL, "手机号为空");
}
return;
}
// 参数合法性检查
Pattern pattern = Pattern.compile("1\\d{10}");
Matcher matcher = pattern.matcher(phoneNum);
if (!matcher.matches()) {
if (listener != null) {
listener.onFailure(ErrorEvent.PARAM_ILLEGAL, "手机号不正确");
}
return;
}
// 请求Api
new AsyncTask<Void, Void, ApiResponse<Void>>() {
@Override
protected ApiResponse<Void> doInBackground(Void... voids) {
return api.sendSmsCode4Register(phoneNum);
}
@Override
protected void onPostExecute(ApiResponse<Void> response) {
if (listener != null && response != null) {
if (response.isSuccess()) {
listener.onSuccess(null);
} else {
listener.onFailure(response.getEvent(), response.getMsg());
}
}
}
}.execute();
}
@Override
public void register(final String phoneNum, final String code, final String password, final ActionCallbackListener<Void> listener) {
// 参数为空检查
if (TextUtils.isEmpty(phoneNum)) {
if (listener != null) {
listener.onFailure(ErrorEvent.PARAM_NULL, "手机号为空");
}
return;
}
if (TextUtils.isEmpty(code)) {
if (listener != null) {
listener.onFailure(ErrorEvent.PARAM_NULL, "验证码为空");
}
return;
}
if (TextUtils.isEmpty(password)) {
if (listener != null) {
listener.onFailure(ErrorEvent.PARAM_NULL, "密码为空");
}
return;
}
// 参数合法性检查
Pattern pattern = Pattern.compile("1\\d{10}");
Matcher matcher = pattern.matcher(phoneNum);
if (!matcher.matches()) {
if (listener != null) {
listener.onFailure(ErrorEvent.PARAM_ILLEGAL, "手机号不正确");
}
return;
}
// TODO 长度检查,密码有效性检查等
// 请求Api
new AsyncTask<Void, Void, ApiResponse<Void>>() {
@Override
protected ApiResponse<Void> doInBackground(Void... voids) {
return api.registerByPhone(phoneNum, code, password);
}
@Override
protected void onPostExecute(ApiResponse<Void> response) {
if (listener != null && response != null) {
if (response.isSuccess()) {
listener.onSuccess(null);
} else {
listener.onFailure(response.getEvent(), response.getMsg());
}
}
}
}.execute();
}
@Override
public void login(final String loginName, final String password, final ActionCallbackListener<Void> listener) {
// 参数为空检查
if (TextUtils.isEmpty(loginName)) {
if (listener != null) {
listener.onFailure(ErrorEvent.PARAM_NULL, "登录名为空");
}
return;
}
if (TextUtils.isEmpty(password)) {
if (listener != null) {
listener.onFailure(ErrorEvent.PARAM_NULL, "密码为空");
}
return;
}
// TODO 长度检查,密码有效性检查等
// 请求Api
new AsyncTask<Void, Void, ApiResponse<Void>>() {
@Override
protected ApiResponse<Void> doInBackground(Void... voids) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String imei = telephonyManager.getDeviceId();
return api.loginByApp(loginName, password, imei, LOGIN_OS);
}
@Override
protected void onPostExecute(ApiResponse<Void> response) {
if (listener != null && response != null) {
if (response.isSuccess()) {
listener.onSuccess(null);
} else {
listener.onFailure(response.getEvent(), response.getMsg());
}
}
}
}.execute();
}
@Override
public void listCoupon(final int currentPage, final ActionCallbackListener<List<CouponBO>> listener) {
// 参数检查
if (currentPage < 0) {
if (listener != null) {
listener.onFailure(ErrorEvent.PARAM_ILLEGAL, "当前页数小于零");
}
}
// TODO 添加缓存
// 请求Api
new AsyncTask<Void, Void, ApiResponse<List<CouponBO>>>() {
@Override
protected ApiResponse<List<CouponBO>> doInBackground(Void... voids) {
return api.listNewCoupon(currentPage, PAGE_SIZE);
}
@Override
protected void onPostExecute(ApiResponse<List<CouponBO>> response) {
if (listener != null && response != null) {
if (response.isSuccess()) {
listener.onSuccess(response.getObjList());
} else {
listener.onFailure(response.getEvent(), response.getMsg());
}
}
}
}.execute();
}
}
简单的实现代码就是这样,其实,这还有很多地方可以优化,比如,将参数为空的检查、手机号有效性的检查、数字型范围的检查等等,都可以抽成独立的方法,从而减少重复代码的编写。异步任务里的代码也一样,都是可以通过重构优化的。另外,需要扩展时,比如添加缓存,那就在调用Api之前处理。 核心层的逻辑就是这样了。最后就到界面层了。