一.前言
最近一直在研究一些关于架构的东西,lz是那种有强迫症的人,就是对于解耦有非常大的渴望,我理想中的架构是每一层各有各的工作,互不干扰。由于lz是学了javaWeb以后开始转到Android,在学习过程中也接触过各种语言和成熟的项目,所以之前一直都是沿用MVC这种代码结构,一直觉得挺好用的。
但是,在Android中,可能如果是简单的小项目,MVC确实很直接暴力,而且很容易入门,就是那种想要什么就拿什么的状态。可是当你的项目涉及的功能越多,在一个Activity中,要做的事也就越多,使用MVC结构的项目的代码非常非常丑,而且非常冗余
二.MVP与MVC的分析
传统的MVC结构
MVC结构我们肯定有接触,在MVC结构中,Activity代表Control,Layout就是View层,然后各种驱动器就是Model层。
在Activity中有时会做很多ui相关的逻辑,然后当要展示新的数据给用户看的时候,就要调用Model层的驱动器来获取数据,所以在MVC的结构中,Activity占据了重量级的位置
缺点:
当遇到一个Activity中涉及到多个功能模块的时候,不方便进行单个模块的调试,而且业务逻辑很难脱离出来。
MVP模式
MVP模式就是MVC的加强版,在MVP中,Activity作为View层,而不再是Control,这就意味这Activity只负责ui的处理,就好比说dialog的展示和各种按键的监听。那关于数据的处理和分发就落到了Presenter的身上,Presenter的任务就是告诉ui层要做什么事,Presenter还负责从Model获取数据,然后对数据进行二次加工处理然后展示到ui层,在这里View和Model就是完全脱离的,没有一点耦合。
lz从最近的俩个项目都是开始使用MVP模式,总结出来MVP有这几个明显的优点:
- view层完全脱离model层,所以重用性非常好和维护成本降低
- view层的逻辑由Presenter控制,所以对于那些只展示数据的view,有时可以多个view适配一个Presenter
- view层和presenter抽取接口,所以对于各个模块做了什么事都显得清晰可见
三.Demo
下面就是lz同一个项目的包结构对比
传统的mvc模式
mvp模式
在mvp模式有很明显的分层,model与view的交流通过presenter来完成,在看看其中一个view(登录):
/**
* Created by 12262 on 2016/5/17.
* 登录页面的方法
*/
public interface LoginView {
/**
* 弹出一个错误提示对话框
* @param content
*/
void showErrorDialog(String content);
/**
* 弹出一个加载中的对话框
*/
void showLoadingDialog();
/**
* 隐藏加载对话框
*/
void hideLoadingDialog();
/**
* 跳到主页面
*/
void runMainAct();
}
上面的代码就包含了presenter控制view的方法,presenter通过构造函数传入的view,从而实现view的逻辑控制,下面看看Presenter:
/**
* Created by 12262 on 2016/5/17.
* 登录页面的大脑
*/
public interface LoginPre {
void login(String username,String password);
}
是的你没看错,只需要一个方法就够了,也就是在Activity中创建一个presenter的实例,然后Activty监听登录按钮(ui的监听都属于view层的工作),然后调用LoginPre.login,在LoginPre中存在Activity的抽取接口类,只需要调用接口类中的方法即可实现对view层的控制,下面是presenter的实现类:
/**
* Created by 12262 on 2016/5/17.
* 登录页面大脑的实现类
*/
public class LoginPreImpl implements LoginPre {
//Model层实现类
OfficeModel model;
LoginView view;
public LoginPreImpl(LoginView view) {
this.view = view;
model = new OfficeModelImpl();
}
@Override
public void login(String username, String password) {
view.showLoadingDialog();
model.Login(username, password)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Html_Main>() {
@Override
public void onCompleted() {
view.hideLoadingDialog();
}
@Override
public void onError(Throwable e) {
view.showErrorDialog(((MyException) e).getViewErrorInfo());
}
@Override
public void onNext(Html_Main html_main) {
//全局化数据
Glo.html_main = html_main;
ConstantValue.isOfficeLogin = true;
view.runMainAct();
}
})
;
}
public void catchError(Throwable e) {
}
}
就这样在MVP模式中完成一个操作,多么优美的结构。
MVP另外一个优点->更方便单元测试
对于大型或者功能较多的项目来说,测试某一个模块的功能是否能完成工作是一个很重要的点,在MVP模式中,由于层与层的分离,你完完全全可以取出一个模块来进行测试,例如现在我想测试登录功能:
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
public void testLibLogin(){
OfficeModel model = new OfficeModelImpl();
//RxJava
model.Login("username","password")
.subscribe(new Observer<Html_Main>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
//登录失败,检查错误原因
}
@Override
public void onNext(Html_Main html_main) {
//登录成功
}
});
}
}