概述
-
定义
MVP 其实是 MVC 的一种演进版本,它更简单,将 MVC 中的 Controller 改为了 Presenter,View 通过接口与 Presenter 进行交互,降低耦合,方便进行单元测试。View:负责绘制 UI 元素、与用户进行交互(Activity、View、Fragment 都可以做为 View 层);
Model:对数据的操作、对网络等的操作,和业务相关的逻辑处理;
Presenter:作为 View 与 Model 交互的中间纽带,处理与用户交互的逻辑。可以把 Presenter理解为一个中间层的角色,它接受 Model 层的数据,并且处理之后传递给 View 层,还需要处理 View 层的用户交互等操作。 作用
1、将Model与View彻底分离。
2、解决MVC中Activity职责过多,代码臃肿的问题-
三者关系
MVP案例
此实例基于MVC的实例,改造为MVP模式。与MVC不同的是,一般Activty会当作View层来处理
-
Model层
跟MVC不同的地方在于Model不会跟View发生交互,只会跟Presenter交互,实现了View和Model的完全分离。
data class UserModel(var userName:String){
fun login(result: Int, listener: ModelCallBack){
if (result == 1){
listener.onSuccess("${userName}登录成功")
}else{
listener.onFailed("${userName}登录失败")
}
}
//回调接口 根据是否成功返回数据
interface ModelCallBack{
fun onSuccess(msg:String)
fun onFailed(msg:String)
}
}
-
View层
在MVP中Activity充当View层角色,并持有Presenter对象的引用。
创建IView接口,由Activity(即View层)实现方法,并暴露给Presenter调用,用于更新View。
interface IView {
fun updateUI(msg:String)
}
Activity类:
class MainActivity : AppCompatActivity(),IView{
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val userPresenter = UserPresenter(this)
//点击事件 模拟向服务器请求登录
loginBtn.setOnClickListener{
userPresenter.login()
}
}
//实现更新界面的方法 暴露给Present调用
override fun updateUI(msg:String) {
textView.text = msg
}
}
-
Presenter层
Present作为中间层,负责业务逻辑处理。
创建IPresenter接口,由Present层实现,暴露给View层调用
interface IPresenter{
fun login()
}
Presenter类
class UserPresenter : UserModel.ModelCallBack,IPresenter{
lateinit var userModel:UserModel
lateinit var iView:IView
constructor(iView: IView){
this.iView = iView
userModel = UserModel("用户${(0..9).random()}")
}
override fun onSuccess(msg: String) {
iView.updateUI(msg)
}
override fun onFailed(msg: String) {
iView.updateUI(msg)
}
override fun login() {
userModel.login((0..1).random(),this)
}
}
运行结果
MVP关键点
View 不再负责同步的逻辑,而是由 Presenter 负责。Presenter 中既有业务逻辑也有同步逻辑。
View 需要提供操作界面的接口给 Presenter 进行调用。(关键)
-
与MVC的不同
对比在 MVC 中,Controller 是不能操作 View 的,View 也没有提供相应的接口;而在 MVP
当中,Presenter 可以操作 View,View 需要提供一组对界面操作的接口给 Presenter 进行调
用;Model 仍然通过事件广播自己的变更,但由 Presenter 监听而不是 View。
MVP的优缺点
-
优点
便于测试。Presenter 对 View 是通过接口进行,在对 Presenter 进行不依赖 UI 环境的单元测试的时候。可以通过 Mock 一个 View 对象,这个对象只需要实现了View 的接口即可。然后依赖注入到 Presenter中,单元测试的时候就可以完整的测试 Presenter 业务逻辑的正确性。
View 可以进行组件化。在 MVP 当中,View 不依赖 Model。这样就可以让 View 从特定的业务场景中脱离出来,可以说 View 可以做到对业务逻辑完全无知。它只需要提供一系列接口提供给上层操作。这样就可以做高度可复用的 View 组件。
-
缺点
维护成本相对较高。Presenter 中除了业务逻辑以外,还有大量的 View->Model,Model->View 的手动同步逻辑,造成Presenter 比较笨重,维护起来会比较困难。
系统内存不足时,系统会回收Activity。一般我们都是用OnSaveInstanceState()去保存状态,用OnRestoreInstanceState()去恢复状态。但是在我们的MVP中,View层是不应该去直接操作Model的,所以这样做不合理,同时也增大了M与V的耦合。解决办法是不要将Activity作为View层,可以把Activity当Presenter来处理。具体实现这里就不分析了,有兴趣的可以研究一下。
UI改变的话,比如TextView 替换 EditText,可能导致Presente的一些更新UI的接口也跟着需要更改,存在一定的耦合。