人之所以能,是相信能。
说到MVP,大家应该都不陌生了,由于其高度解等等优点,越来越多的项目使用这个设计模式。然而,优点虽在,缺点也不少,其中一个就是类多了很多,而且V与P直接要项目通信,那么P就得持有V得实例,但如果活动挂掉了,如果没有对V进行释放,还有导致内存溢出得问题,而且,那么多的接口函数,看得到人眼花缭乱,也使得很多人在使用这个模式的时候望而尚步。
回归正题,最近在进行代码重构,决定采用MVP模式进行开发。如果我们不进行封装,单纯地简单使用MVP来开发,这要就会出现如上的问题,接口和类多而且重复。和别人协同开发也存在问题。那么对MVP模式进行封装就显得很重要了。当然,一千个人中有一千个哈姆雷特,这里提供一下我的思路,供大家参考。
什么是MVP模式
MVP模式相当于在MVC模式中又加了一个Presenter用于处理模型和逻辑,将View和Model完全独立开,在android开发中的体现就是activity仅用于显示界面和交互,activity不参与模型结构和逻辑。
使用MVP模式会使得代码多出一些接口但是使得代码逻辑更加清晰,尤其是在处理复杂界面和逻辑时,我们可以对同一个activity将每一个业务都抽离成一个Presenter,这样代码既清晰逻辑明确又方便我们扩展。当然如果我们的业务逻辑本身就比较简单的话使用MVP模式就显得,没那么必要。所以我们不需要为了用它而用它,具体的还是要要业务需要。
其实,简而言之:view就是UI,model就是数据处理,而persenter则是他们的纽带。
使用MVP的结构再对比下MVC
MVP模式还是存在一些不足之处的,最大的不足就是类的快速增多,但相对于MVC的臃肿、MVP的高度解耦来说,类的增多可能就洒洒水啦
~
封装思路
上图介绍:
Contract:契约类,一个功能模块中View接口、Model接口和请求数据回调统一在对应模块的Contract中定义,便于管理。
ViewInterface: view层接口,定义了view中的UI操作
ModelInterface: model层接口,定义了model负责的数据操作方法,如请求接口,操作数据库等
CallbackInterface: model层操作数据完成后的回调
BasePersenter: Persenter父类,主要是对相关view的获取,销毁等操作
View: view层实现类,主要就是Activity或Fragment,负责UI展示和事件响应
Model: model层实现类,就是依据业务,请求对应接口或数据库,并将结果返给回调CallBack
Persenter: persenter层类,负责业务逻辑处理,view将响应传给persenter,persenter负责调用model,并将结果返回给view供其展示
框架封装1、Presenter的封装
先来观察下这个base类:
先设置一泛型T,T为与presenter相关的view。BasePresenter中持有一个view的软引用。
在关联方法中将view对象传入,并存入软引用中,创建获取、取消关联和判断方法。
至于使用软引用,是为了防止所持的view都销毁了,但presenter一直持有,导致内存泄漏。
2、view的封装
view的封装,主要是BaseActivity和BaseFragment的封装。
2.1、BaseActivity
BaseActivity设置两个泛型——V和P,明显地,分别代表对应的View和Presenter。
其持有一个BasePresenter,在onCreated方法中,使用createPresenter方法返回对应的BasePresenter的子类,我们就可以使用了。
这里注意一下view和presenter的处理:在onCreated中创建Presenter对象,但其内部的view软引用还是空;在onResume中关联view,此时presenter已经持有view的软引用;当然,还需要在onDestroy中取消关联。
至于其他的封装就不再介绍了,相信大家肯定还有更优的封装方法。
2.2 BaseFragment
BaseFragment与BaseA类似就不再累赘。
3、Contract契约类
契约,顾名思义,规范定义,定义功能和模板。
在契约类中定义View的接口,Model的接口。因为Model将数据返给Presenter是使用回调方式,所以还需要再契约类中定义对应的回调。
具体看示例吧。
实战
这里我们以登录功能模块为例:
1、契约类
这里定义了登录页面的view接口、model接口和对应的回调。
在view中,只定义与UI展示的相关方法,如检查账号密码格式成功(失败)、登录成功(失败)等。
model负责数据请求,所以在接口中只定义了登录的方法。
回调定义了登录成功还是失败的方法。
2、Model实现类
创建Model实现类,重写其登录方法既可,将登录接口交给回调。
3、Presenter
LoginPresenter集成BasePresenter,传入LoginView最为泛型T。
内部持有Model实现类对象。
创建两个方法,一个是检查格式,一个是登录。两个方法就是业务的处理。
如登录方法,登录返回后,在回调中得到数据,也可以再进行一些逻辑判断,将结果交给view的对应的方法。
注意这里使用getView()方法就可以,因为在父类中getView方法直接返回的对应的view实例。
4、View
这里的LoginActivity就是登录功能模块的view,其集成BaseActivity,传入view和presenter泛型。
实现LoginView接口,重写接口定义好的UI方法。
在createPresenter方法中创建LoginPresenter对象并返回。这样,就可以使用mPresenter直接操作逻辑了。
再看下整个功能模块的事件流和数据流
大致就是这样了,有不足的地方大家多提意见。^_^
领取专属 10元无门槛券
私享最新 技术干货