两者都是 解耦视图与业务逻辑 的架构模式,解决传统 MVC 中 Activity/Fragment 职责过重的问题。
1. MVP
角色分工
View:Activity / Fragment,持有 Presenter 引用;负责 UI 展示、用户交互。
Presenter:中间层,同时持有 View 和 Model 引用。接收 View 的事件,调用 Model 做业务,拿到结果后回调 View 接口更新 UI。
Model:数据层(网络、数据库)。
核心特点:接口驱动
Presenter 通过 View 接口 和 View 通信。
plaintext
View <--> Presenter <--> Model
View持有Presenter,Presenter持有View接口
示例伪代码:
kotlin
// 定义View接口
interface IImageView{
fun showImage(bitmap:Bitmap)
}
class ImagePresenter(val view:IImageView){
fun loadImage(){
val bitmap = Model.getImage()
view.showImage(bitmap) // 主动调用view接口
}
}
class MainActivity:Activity,IImageView{
val presenter = ImagePresenter(this)
override fun showImage(bitmap: Bitmap) {
iv.setImageBitmap(bitmap)
}
}
✅优点
职责清晰,Presenter 纯 Java/Kotlin,方便单元测试,不依赖 Android 框架。
View 和 Model 完全隔离。
❌缺点
大量 View 接口,页面复杂后接口爆炸;每一个 UI 变化都要新增接口方法。
Presenter 持有 View 引用,页面销毁时如果没有及时清空引用,容易内存泄漏。
UI 变更全部需要 Presenter 主动调用接口,大量样板代码。
2. MVVM
角色分工
View:Activity/Fragment/xml 布局,只负责页面显示。
ViewModel:存放业务逻辑与页面状态,不持有 View 引用。
Model:数据层。
DataBinding / ViewDataBinding:双向绑定桥梁,View 观察 ViewModel 的数据变化,自动刷新 UI。
plaintext
View <--(DataBinding双向绑定)--> ViewModel <--> Model
ViewModel不知道View的存在
伪代码:
kotlin
class ImageViewModel:ViewModel(){
// 可观察数据,数据变化自动通知UI
val imageBitmap = MutableLiveData<Bitmap>()
fun loadImage(){
val bitmap = Model.getImage()
imageBitmap.postValue(bitmap) // 修改数据,xml自动刷新界面
}
}
// xml布局中绑定imageBitmap,数据一变自动更新ImageView,不需要写大量setXXX
✅优点
ViewModel 不持有 View,没有 View 引用,从根源减少内存泄漏风险;屏幕旋转配置变更,ViewModel 自动存活。
告别大量 View 接口,通过可观察数据(LiveData/StateFlow)驱动 UI,样板代码少。
同样方便单元测试 ViewModel。
❌缺点
DataBinding 会增加编译时间;xml 里写业务逻辑,调试困难。
双向绑定用不好容易出现数据互相循环触发。
复杂页面,ViewModel 会变得很臃肿,需要做好拆分。
3. 核心区别(面试背诵版)
表格
一句话总结:
MVP:Presenter 主动指挥 View 干活;MVVM:View 监听 ViewModel 的数据,数据变了 UI 自动更新。
4. 面试高频延伸问题(很容易被追问)
Q1:Android 中 ViewModel 为什么不怕屏幕旋转?
ViewModel 存在 ViewModelStore,由 ViewModelProvider 管理,Activity 重建不会销毁 ViewModel 实例,新 Activity 重新拿到同一个 ViewModel 对象。
Q2:MVVM 是不是必须用 DataBinding?
不是!
现在很多项目不用 DataBinding,用 LiveData / StateFlow + 观察回调,就是单向 MVVM。
View 观察 ViewModel 的 LiveData,收到数据回调手动更新 UI,不开启双向绑定。这是现在 Android 主流写法。
Q3:MVP 内存泄漏怎么解决?
页面onDestroy的时候,把 Presenter 里的 View 引用置为 null,切断持有关系。
Q4:影像 APP 这种复杂图形页面,你会选哪个?
面试回答参考:
简单页面 MVP 足够;复杂页面优先 MVVM,ViewModel 管理页面状态,Camera、滤镜参数状态放到 ViewModel,屏幕旋转不用重新初始化相机;图形渲染 Surface/TextureView 这种特殊视图,DataBinding 不好处理,采用单向观察,不用强双向绑定。
5. 踩坑补充(加分项)
MVP 最大痛点:接口爆炸;
MVVM 最大坑:ViewModel 无限膨胀,要按业务拆分多个 ViewModel,不要把所有逻辑塞一个;
不要把 Android 组件(Context、Activity)直接传入 ViewModel,会造成内存泄漏,要用 Application 的 Context。