MVP架构由浅入深篇三(终极版)
前言:在从基础版MVP架构优化成进阶版MVP架构的过程中,几乎每个单元都做了很大优化并封装到了base层,但是唯独Model层没什么变化。所以,终极版MVP架构的优化主要就是对Model层的优化。
一、Model单独封装,集中管理
先看一下整体的架构模型先:
Model层相比其他单元来说其功能就是通过回调接口向上层返回数据。再就是MVP的理念是让业务逻辑互相独立,这就导致每个的网络请求也被独立成了单个Model,这种方式在实际开发中就会出现一些问题:
- 无法对所有Model统一管理。
- 每个Model对外提供的获取数据方法有差异,没有统一规范。
- 代码冗余高,网络数据请求除URL和参数外其他大概都一样的。
- 对已存在的Model管理困难,不能直观的统计已存在的Model。
所以我们更希望Model层是一个庞大且独立单一模块,请求方式规范化,管理Model更加直观。
从上面的框架图可以看出,Presenter 请求数据不再直接调用具体的Model对象,统一以 DataModel
类作为数据请求层的入口,以常量类 Token
区别具体请求。 DataModel会根据Token的不同拉取底层对应的具体Model。
二、代码实现
从上面的流程如图可知:
DataModel
: 数据层顶级入口,项目中所有数据都由该类流入和流出,负责分发所有的请求数据。Token
:数据请求标识类,定义了项目中所有的数据请求。BaseModel
:所有Model的顶级父类,负责对外提供数据请求标准,对内为所有Model提供请求的底层支持。
1.BaseModel实现
BaseModel中定义了对外的请求数据规则,包括设置参数的方法和设置Callback的方法,还可以定义一些通用的数据请求方法,比如说网络请求的Get和Post方法。
package com.example.mvpapplication.basemodel;
import com.example.mvpapplication.base.Callback;
import java.util.Map;
public abstract class BaseModel <T>{
//数据请求参数
protected String[] params;
/**
* 设置数据请求参数
* @param args
* @return
*/
public BaseModel setParams(String...args){
this.params = args;
return this;
}
/**
* 抽象方法,具体实现由子类实现
* @param callback
*/
public abstract void execute(Callback<T> callback);
protected void requestGetAPI(String url,Callback<T> callback){
//这里写get API方法请求网络数据
}
protected void requestPostAPI(String url, Map params,Callback<T> callback){
//这里写post API方法请求网络数据
}
}
2.DataModel实现--(model-one)
package com.example.mvpapplication.basemodel;
import android.os.Handler;
import com.example.mvpapplication.base.Callback;
public class UserDataModel extends BaseModel<String> {
@Override
public void execute(final Callback<String> callback) {
//模拟网络请求
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
switch (params[0]){
case "nomal":
callback.onSuccess("根据参数"+params[0]+"的请求网络数据成功");
break;
case "failure":
callback.onFailure("失败");
break;
case "error":
callback.onError();
break;
}
callback.onComplete();
}
},2000);
}
}
3.DataModel实现
DataModel的功能主要是根据token管理每个model,所以采用反射机制来得到实例,其中token就是“包名+类名”。
package com.example.mvpapplication.basemodel;
public class DataModel {
public static BaseModel request(String token){
BaseModel model = null;
try {
model = (BaseModel) Class.forName(token).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return model;
}
}
4.Token的实现
package com.example.mvpapplication.basemodel;
public class Token {
// 包名 com.example.mvpapplication.basemodel.
private static final String PACKAGE_NAME = "com.example.mvpapplication.basemodel.";
// 具体Model
public static final String API_USER_DATA = PACKAGE_NAME + "UserDataModel";
}
5.如何使用?
package com.example.mvpapplication;
import com.example.mvpapplication.base.BasePresenter;
import com.example.mvpapplication.basemodel.DataModel;
import com.example.mvpapplication.basemodel.Token;
/**
* 这里相当于中介的作用
*/
public class MvpPresenter extends BasePresenter<MvpView> {
//因为中介要和雇主打交道,所以要声明MvpView
private MvpView mView;
public MvpPresenter(){}
public MvpPresenter(MvpView view){
this.mView = view;
}
/**
* 相当于帮我找房子--请求数据
* @param param
*/
public void getData(String param){
if (!isViewAttached())
return;
//显示正在加载进度条
getView().showLoading();
//调用新版Model请求数据
DataModel.request(Token.API_USER_DATA).setParams("user").execute(new MvpCallback() {
@Override
public void onSuccess(String data) {
//调用view接口显示数据
if (isViewAttached()){
getView().showData(data);
}
}
@Override
public void onFailure(String msg) {
if (isViewAttached()){
getView().showToast(msg);
}
}
@Override
public void onError() {
if (isViewAttached()){
getView().showErr();
}
}
@Override
public void onComplete() {
if (isViewAttached()){
getView().hideLoading();
}
}
});
}
}
总结
经过优化的Model层很好的统一化了请求方法规范,利用BaseModel不仅有效的减少了数据请求的冗余代码,最关键的还是得到了将所有Model的集中控制权。
如果要新添加一个model:
- 新建一个Model并继承BaseModel,完成具体的数据请求。
- 在Token中添加对用的Model包名+类名。
至此,终极版MVP框架已经分析完了,从最初的基础版-->进阶版-->终极版,我们进行了一步一步的优化,使代码复用率更高,逻辑层次更加清晰,漏洞越来越少,框架越来越强大。但是MVP之路还没有结束,根据具体的项目需求,可以对框架进行有针对性地修改,使之更加匹配自己的项目需求。