先说说MVP和MVC的区别吧,MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。
在MVC里,View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑。 在MVC模型里,更关注的Model的不变,而同时有多个对Model的不同显示,及View。所以,在MVC模型里,Model不依赖于View,但是View是依赖于Model的。不仅如此,因为有一些业务逻辑在View里实现了,导致要更改View也是比较困难的,至少那些业务逻辑是无法重用的。
MVP针对MVC主要是取消掉了Model和View的直接通信,降低了耦合程度,主要的程序逻辑在Presenter里实现,这样在再经历UI大改版的时候业务逻辑也不会受到影响,我们改变的也只是View这块,既然是对MVP进行优化,先说说MVP的优点吧:
1.Model和View分离,View变化时不会影响Model
2.Model更容易管理,因为控制它的只有Presenter
3.主要逻辑放在Presenter中,易于管理和维护就不说了,像这块逻辑的完全可以单独作为一个Lib,作为一个java model 引入项目中,也方便进行业务测试
4.项目迁移方便,像一个视频直播平台,如果有多个app需要开发,那么这块业务逻辑完全是可以公用的,手机版和pad版或者是tv版,唯一不同的也就只有View不同,难道要copy3份代码,这样变更业务逻辑的时候将是相当痛苦的
每种设计模式都有优点和缺点,接下来就是MVP的缺点了:
1.每个View有个Presenter,界面一多,就比较头疼了
2.多个Presenter管理不当可能造成业务处理耦合
3.每个Presenter都要为View里定义接口,有些定义了还无法重用,定义的接口太乱,有时会重复
当然还有Mvvm模式Model-View-ViewModel ,google也提供了Data Binding 的方式,但是这种方式会把xml变得不再只是个单纯的View,Model一旦改动,还要改xml,xml的重用性也不高,因此不推荐此方式。
接下来就是针对MVP的不足进行改造成适合自己的结构了,当然这三者的通信方式不会变动,现在对结构做出调整,一个View可以拥有多个Presenter,每个Presenter负责不同的业务,这里举例只有一个
这里没有说明Model,Model定义为获取数据的模型,实现方式有多样,首先定义View->Presenter和Presenter -> View的通信接口,为后面扩展方便
/**
*
* Presenter -> View 进行通信
*/
public interface PresenterListener {
}
/**
* 定义些给View操作的方法
* View->Presenter 进行通信
*/
public interface I_UserPresenter {
void login();
void getInfo();
interface OnGetUserInfoListener extends PresenterListener {
void onGetUserInfo(Object info);
}
/**
* 向Presenter触发业务操作
*
* @param roomId
*/
void subUser(String roomId);
void unSubUser(String roomId);
/**
* 向View通知状态
*/
interface OnSubListener extends PresenterListener {
/**
* 返回订阅状态
*
* @param isSub
*/
void onSubChange(boolean isSub);
}
}
再看下Presenter的具体实现
public class UserPresenter extends CorePresenter implements I_UserPresenter {
private OnGetUserInfoListener onGetUserInfoListener;
private OnSubListener onSubListener;
@Override
public void login() {
log("login");
}
@Override
public void getInfo() {//可以根据不同的需求是读缓存还是网络,走不同的逻辑
log("getinfo");
if (onGetUserInfoListener != null) {
onGetUserInfoListener.onGetUserInfo("test infos");
}
}
@Override
public void subUser(String roomId) {
if (onSubListener != null) {
//这里处理订阅的操作..省略
log("subUser");
onSubListener.onSubChange(true);
}
}
@Override
public void unSubUser(String roomId) {
if (onSubListener != null) {
//这里处理取消订阅的操作..省略
log("unSubUser");
onSubListener.onSubChange(false);
}
}
@Override
public void addListener(PresenterListener listener) {
super.addListener(listener);
if (listener instanceof OnGetUserInfoListener) {
this.onGetUserInfoListener = (OnGetUserInfoListener) listener;
} else if (listener instanceof OnSubListener) {
this.onSubListener = (OnSubListener) listener;
}
}
}
再看下View里的结构
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!mIsSub) {
userPresenter.subUser("");
} else {
userPresenter.unSubUser("");
}
}
});
findViewById(R.id.tv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
userPresenter.getInfo();
}
});
userPresenter = new UserPresenter();
userPresenter.addListener(onSubListener);//动态配置所需要的业务
userPresenter.addListener(new I_UserPresenter.OnGetUserInfoListener() {
@Override
public void onGetUserInfo(Object info) {
Toast.makeText(getBaseContext(), String.valueOf(info), Toast.LENGTH_LONG).show();
}
});
}
/**
* View处理Presenter 相应的数据
*/
private UserPresenter.OnSubListener onSubListener = new UserPresenter.OnSubListener() {
@Override
public void onSubChange(boolean isSub) {
mIsSub = isSub;
Snackbar.make(fab, "订阅状态" + isSub, Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
};
说下这样改的好处吧:
1.归类了Presenter,每个Presenter都有自己明确的职责,避免每个View都会有个Presenter 造成后续难以管理
2.每个Presenter可能有多个业务要处理,但不是每个都需要,可以通过添加Listener来去做需要的业务,这样不会造成一下子定义太多接口,有些接口在某些地方更不不需要
3.基本上Presenter每个业务处理都只匹配一个Listener,业务逻辑由Presenter来控制,方便一些好用的异步处理框架的快速切入(比如RxJava)和更换
4.代码量会减少
5.偶尔性降低
PS:适合自己的才是好的,框架不能定死了,个人见解而已,欢迎大家指出意见。