MVP 是最早被广泛应用于 Android 的架构模式之一,它的核心目标是将视图(View)与业务逻辑(由 Presenter 负责)彻底解耦。
Presenter
(主持人)作为 View
和 Model
之间的桥梁。View
的所有用户操作都委托给 Presenter
处理,Presenter
处理完业务逻辑后再回调 View
的接口来更新界面。View
和 Presenter
通常通过一个 Contract
(契约)接口来定义彼此的交互。
Activity
/Fragment
)。负责展示 UI 和响应用户输入,并将所有业务逻辑操作全权委托给 Presenter
。它通常会实现一个 IView
接口。View
和 M
odel 的引用。它从 Model
获取数据,处理业务逻辑,并调用 View
的接口来更新 UI。Presenter 不应包含任何 Android 框架的代码,这使其易于进行单元测试。View
和 Presenter
的所有交互方法,使得它们之间的通信一目了然。优点:
View
和 Model
完全分离。Presenter
不依赖任何 Android SDK,方便进行 JVM 单元测试。缺点:
Contract
接口和实现类,代码量较大。Presenter
和 View
通过接口紧密耦合,通常是一对一的关系,复用性不强。Presenter
容易变得臃肿。MVP 模式在新的 Android 项目中已较少使用,其设计思想已被更现代的模式所吸收和超越。但理解 MVP 对于理解后续架构的演进非常有帮助。
随着 Google 推出 Jetpack 组件库,MVVM 迅速成为 Android 社区的主流和官方推荐架构。
MVVM 的核心是数据绑定和生命周期感知。ViewModel
不直接持有 View
的引用,而是通过暴露可观察的数据流(LiveData
或 StateFlow
),View
订阅这些数据流并在数据变化时自动更新 UI。这是一种从“命令式”(presenter.showUser(user)
)到“声明式”(observe(viewModel.userState)
)的转变。
Activity
/Fragment
)。职责变得更纯粹,主要是观察 ViewModel
暴露的数据状态,并据此渲染 UI。它持有对 ViewModel
的引用。View
所需的数据和状态,并处理用户的交互。它通过 viewModelScope
协程作用域来执行业务逻辑。ViewModel
是生命周期感知的,能在配置变更(如屏幕旋转)后存活下来,并自动在宿主(Activity
/Fragment
)销毁时清理资源。优点:
ViewModel
不持有 View
的引用,可以实现一对多的关系(一个 ViewModel
可被多个 View
共享),复用性强。ViewModel
不含 Android 框架代码,易于单元测试。缺点:
ViewModel
可能会引入一些额外的模板代码。MVVM 是当前 Android 开发的基石和标准实践。结合 Kotlin、协程和 Jetpack Compose,MVVM 架构能提供极佳的开发体验和应用质量。
MVI 是一种更现代、更函数式编程思想的架构模式,它在 MVVM 的基础上,对状态管理提出了更严格的规范。
MVI 的核心是单向数据流 (Unidirectional Data Flow) 和单一数据源 (Single Source of Truth)。整个应用的状态被建模为一个不可变 (Immutable) 的状态对象。UI 的任何变化都源于一个新的状态对象。
数据流是一个循环:
View
将用户操作(如点击按钮、输入文本)封装成一个 Intent
对象发送出去。注意:此 Intent 非 Android 的 Intent
类,而是代表一个用户行为或意图。ViewModel
或类似的业务逻辑层接收 Intent
,根据 Intent
内容处理业务逻辑,并基于当前状态生成一个新的状态 (State)。ViewModel
将新的 State
对象通过可观察的数据流暴露出去。View
订阅这个状态流,并在接收到新状态时,完整地渲染整个 UI。ViewModel
内部实现。负责接收 Intent
,处理业务逻辑,并生成新的 State
。Intent
发送出去,以及订阅 State
流并根据最新的 State
渲染自己。优点:
缺点:
State
和 Intent
创建大量的数据类,对于简单页面而言可能过于繁琐。MVI 在处理复杂状态同步的场景下表现出色,在许多大型应用和 Jetpack Compose 社区中越来越受欢迎。它被认为是 MVVM 的一个演进方向,尤其适合对状态管理有严格要求的团队。
特性 | MVP | MVVM | MVI |
---|---|---|---|
核心思想 | 接口回调,命令式 | 数据绑定/观察,声明式 | 单向数据流,不可变状态 |
数据流向 | View ↔Presenter ↔Model |
View →ViewModel ↔Model ViewModel →View |
View →Intent →Model →State →View (环形) |
耦合度 | View 与 Presenter 强耦合 |
View 与 ViewModel 松耦合 |
View 与 ViewModel 松耦合 |
状态管理 | 由 Presenter 分散管理 |
由 ViewModel 暴露状态 |
统一的、不可变的 State 对象 |
主要优点 | 职责分离,易于测试 | 生命周期感知,代码简洁 | 状态可预测,调试方便 |
主要缺点 | 模板代码多,Presenter 易膨胀 | 学习曲线稍高 | 模板代码最多,对简单页面过度设计 |
适用场景 | 旧项目维护 | 绝大多数项目,通用标准 | 复杂状态管理,多人协作的大型项目 |
最终,架构模式是工具而非教条。一个成功的项目往往是根据业务场景,灵活地组合和运用这些模式的智慧结晶。