为什么我突然想学习UML图形建模语言?因为目前开发总是使用别人的开源框架,但是自己对框架也总是局限于使用的技术领域,对框架的的架构和技术实现和设计思想并不关心,开发变得简单了,同时也变的无趣了。UML图形建模工具运用领域广泛,学好这个工具对以后的发展也会有很大的帮助。
UML百度百科
MVP全称是Model、View、Presenter,顾名思义,它将整个应用分为三层:
1)View层:视图层,包含界面相关(Activity、Fragment、View、Adapter),Veiw层一般会持有Presenter的引用,并将非UI逻辑操作委托给Presenter。
2)Presenter层:逻辑控制层,充当中间人的角色,用来隔离View层和Model层,该层是从View层剥离控制逻辑部分而形成的,主要负责Veiw层和Model层的控制和交互。例如接受View层的网络数据加载请求,并分发给对应的Model处理,同时监听Model层的处理结果,最终将其反馈给View层,从而实现界面的刷新。
3)Model层:封装各种数据来源,例如远程网络数据,本地数据库数据等,对Presenter层提供简易易用的接口。
MVP与MVC的区别:
MVP是MVC的延伸和改进,它们之间最大的不同有两点.
1)MVP中View层和Model层并没有直接通信,而是通过之间人Presenter来简洁通信;Presenter和View以及Model的交互都是通过接口进行的;通常View和Presenter是一对一的,当然,复杂的View可能需要多个Presenter来共同处理,这些需要根据具体的业务需求来定。
2)MVC中的Model层和View层是直接通讯的,而且Controller是基于行为的,可以被多个View共享。
公司开发了一个新的项目,项目框架是新同事搭建的,项目上使用了很多的开源流行项目和Java新特性的一些使用及使用MVP模式进行了项目解耦,刚看起来还是有一点难理解,所以写下这篇博客,以供以后参考。
首先先介绍一下项目使用到的一些新技术:
1)RecyclerView.
2 ) Fresco
3 ) RXJAVA+Retrofit+Okhttp网络框架
4)MVP
项目的包结构:
说到项目包结构,必须要先说说MVP,之前我们学过web编程的动知道MVC,MVP是MVC的变种.
MVP的百度百科这个链接把MVP模式介绍挺详细的,也区分了和MVC的区别。
这个包里面主要实现了一些基本的框架配置:
IActivityFragment这个接口定义了一系列的接口方法,然后由BaseActivity和BaseFragment只实现一次,BaseActivity和BaseFragment是抽象类,实现了IActivityFragment接口的所有方法,后续开发定义View只需要继承BaseActivity或者BaseFragment,去选择性的继承抽象类中的方法。IBview和IBPresenter都是接口,这是为了抽取公共的业务逻辑,比如说加载框的显示隐藏,检查用户是否登录等操作。BasePresenter是实现业务的类,该类使用泛型接受单个的Activity或者Fragment对象,通过持有对象来对View层进行调用。
上面定义了那么多,那么我们具体怎么来实现MVP解耦业务和界面呢?
我们以登录为例,看一段代码:
/**
定义一个登录接口,里面有两个接口,一个接口涉及业务IBPresenter和一个接口涉及界面的展示IBview
**/
public interface ILogin {
interface IView extends IBView {
void loginSuccess(TestEntity data);
}
interface IPresenter extends IBPresenter {
void login();
}
}
从代码可以看出,项目的每一个模块的业务都封装成接口的形式,有公共部分就抽取公共的接口,单独的业务逻辑也可以是接口。
具体的业务逻辑操作就需要再创建一个单独的XXXPresenter了,这个XXXPersenter继承BasePersenter,并且实现了IXXX接口,然后通过拿到具体的Activity或者Fragment来进行UI的操作。
/**
业务逻辑的具体实现类,因为继承了BasePresenter类而拿到了Activity或者Fragment实例,实现业务然后操作UI.
**/
public class LoginPresenter extends BasePresenter<ILogin.IView> implements ILogin.IPresenter {
public LoginPresenter(ILogin.IView pView) {
super(pView);
}
@Override
public void login() {
request().get("token").enqueue(newCallback(new NetCallback<NetEntity<TestEntity>>() {
@Override
public void succeed(NetEntity<TestEntity> pData) {
int code = pData.getCode();
String msg = pData.getMsg();
TestEntity data = pData.getData();
mView.loginSuccess(data);
}
@Override
public void failed(NetException pE) {
int code = pE.getCode();
String msg = pE.getMsg();
String toastMsg = pE.getToastMsg();
}
}));
}
}
那我们是如何来调用业务逻辑方法和改变UI的呢?
刚开始我们注意到Acticity和Fragment实现了IActivityFragment接口,并且有具体的实现,包括使用Retrofit网络框架实现网络请求的封装。
/**
* 根据IRequest类获取Request实例,这里接受一个类(JavaBean对象),通过复杂的网络请求之后赋值。
*/
@Override
public final <T> T request(Class<T> pIRequest) {
return NetManager.INSTANCE.request(pIRequest);
}
当然,我们的XXXPersenter如果拿到了具体的Activity和Fragment对象就可以在XXXPersenter的类里面去调用网络请求操作,然后通过接口回调数据来更新UI界面。同时实现findViewById操作,后期可以使用ButterKnife或者EeventBus来省略findViewById操作。OK,MVP模式就实现了!
总结:
1)从上面我们可以发现,我们的每一个Activity或者Fragment创建之后,我们都要先定义一个界面的对应接口,这个接口里面有两个接口,一个接口封装View的操作,一个接口封装业务的操作。
2)创建界面接口之后,我们还有创建一个界面的控制器XXXPresenter,这个是拿到Activity或者Fragment对象,然后调用具体的抽象实现方法,完成方法的调用,然后在更新UI层。
MVP模式缺点:
1)会创建很多的IXXXView接口,里面封装View和逻辑的接口。
2)会创建很多的XXXPresenter类去解耦业务逻辑,导致包结构增大。