Administrator
发布于 2026-08-12 / 15 阅读
0
0

MVP vs MVVM 区别(Android 视角)

两者都是 解耦视图与业务逻辑 的架构模式,解决传统 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)
    }
}

✅优点

  1. 职责清晰,Presenter 纯 Java/Kotlin,方便单元测试,不依赖 Android 框架。

  2. View 和 Model 完全隔离。

❌缺点

  1. 大量 View 接口,页面复杂后接口爆炸;每一个 UI 变化都要新增接口方法。

  2. Presenter 持有 View 引用,页面销毁时如果没有及时清空引用,容易内存泄漏。

  3. 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

✅优点

  1. ViewModel 不持有 View,没有 View 引用,从根源减少内存泄漏风险;屏幕旋转配置变更,ViewModel 自动存活。

  2. 告别大量 View 接口,通过可观察数据(LiveData/StateFlow)驱动 UI,样板代码少。

  3. 同样方便单元测试 ViewModel。

❌缺点

  1. DataBinding 会增加编译时间;xml 里写业务逻辑,调试困难。

  2. 双向绑定用不好容易出现数据互相循环触发。

  3. 复杂页面,ViewModel 会变得很臃肿,需要做好拆分。

3. 核心区别(面试背诵版)

表格

对比维度

MVP

MVVM

View 与中间层关系

Presenter 持有 View 接口,主动调用 View 方法

ViewModel不持有 View;View 观察 ViewModel 数据

UI 更新方式

Presenter 主动调用 View 接口方法更新 UI

数据驱动:数据变化,自动刷新 UI(DataBinding/LiveData)

内存泄漏风险

高,Presenter 持有 View,页面销毁要手动置空

低,ViewModel 不知道 View 存在,生命周期由系统管理

接口数量

大量 IView 接口,页面越复杂接口越多

几乎不需要定义 View 接口

调试难度

逻辑集中在 Presenter,调试简单

数据绑定,xml 中逻辑调试麻烦

生命周期

和 View 绑定,View 销毁需要手动释放

ViewModel 独立生命周期,屏幕旋转不会重建

一句话总结:

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. 踩坑补充(加分项)

  1. MVP 最大痛点:接口爆炸;

  2. MVVM 最大坑:ViewModel 无限膨胀,要按业务拆分多个 ViewModel,不要把所有逻辑塞一个;

  3. 不要把 Android 组件(Context、Activity)直接传入 ViewModel,会造成内存泄漏,要用 Application 的 Context。


评论