安卓应用架构模式 MVC MVP MVVM有什么区别?

server/2025/3/13 6:57:57/

在 Android 开发中,MVCMVP 和 MVVM 是三种常见的架构模式,它们的目标都是通过分层解耦代码,提升可维护性和可测试性。以下是它们的核心区别和实际应用对比:

1. 核心职责划分

架构模式分层结构各层职责
MVCModel-View-ControllerModel: 数据逻辑(数据库、网络请求)
View: UI 显示(XML布局)
Controller: 业务逻辑(Activity/Fragment)
MVPModel-View-PresenterModel: 数据逻辑
View: UI 显示 + 接口(Activity/Fragment 实现)
Presenter: 业务逻辑(纯 Java/Kotlin 类)
MVVMModel-View-ViewModelModel: 数据逻辑
View: UI 显示(XML + Activity/Fragment)
ViewModel: 业务逻辑 + 数据驱动(通过 LiveData/Flow 暴露数据)

 

2. 数据流向

架构模式数据流
MVC单向:用户操作 → Controller → 更新 Model → 通知 View 刷新(但 Controller 可能直接操作 View)
MVP双向:用户操作 → View → Presenter → Model → Presenter → View
MVVM双向:用户操作 → View → ViewModel → Model → ViewModel → View(通过数据绑定自动更新)

 

3. 核心优缺点对比

MVC(传统 Android 开发模式)
  • 优点

    • 结构简单,适合小型项目。

  • 缺点

    • Controller 臃肿:Activity/Fragment 同时承担 View 和 Controller 职责。

    • 测试困难:业务逻辑和 UI 耦合,难以单元测试。

MVP(解耦业务逻辑)
  • 优点

    • 职责清晰:Presenter 独立于 Android API,便于测试。

    • View 被动:通过接口定义交互,降低耦合。

  • 缺点

    • 接口冗余:需要为每个 View 定义大量接口。

    • 手动绑定:需在 View 中主动调用 Presenter 方法。

MVVM(Jetpack 推荐模式)
  • 优点

    • 自动更新:通过数据绑定(如 LiveData + DataBinding)实现 UI 自动刷新。

    • 生命周期感知:ViewModel 自动管理数据,避免内存泄漏。

    • 代码简洁:减少手动更新 UI 的代码。

  • 缺点

    • 学习成本:需掌握 Jetpack 组件(ViewModel、LiveData 等)。

    • 过度绑定:不当使用可能导致逻辑分散到 XML。

4. 代码示例对比

MVC(典型问题)
// Activity 承担 Controller + View 职责
class UserActivity : AppCompatActivity() {private lateinit var textView: TextViewprivate val userModel = UserModel()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_user)textView = findViewById(R.id.text_view)// 直接操作 Model 和 ViewuserModel.fetchUser { user ->textView.text = user.name // Controller 直接更新 View}}
}
MVP(解耦实现)
// View 接口
interface UserView {fun showUserName(name: String)
}// Presenter 类
class UserPresenter(private val view: UserView) {private val userModel = UserModel()fun loadUser() {userModel.fetchUser { user ->view.showUserName(user.name)}}
}// Activity 实现 View 接口
class UserActivity : AppCompatActivity(), UserView {private lateinit var presenter: UserPresenterprivate lateinit var textView: TextViewoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_user)textView = findViewById(R.id.text_view)presenter = UserPresenter(this)presenter.loadUser()}override fun showUserName(name: String) {textView.text = name}
}
MVVM(Jetpack 实现)
// ViewModel
class UserViewModel : ViewModel() {private val _user = MutableLiveData<User>()val user: LiveData<User> = _userinit {loadUser()}private fun loadUser() {UserModel.fetchUser { user ->_user.value = user}}
}// Activity + DataBinding
class UserActivity : AppCompatActivity() {private lateinit var binding: ActivityUserBindingprivate val viewModel: UserViewModel by viewModels()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = DataBindingUtil.setContentView(this, R.layout.activity_user)binding.lifecycleOwner = thisbinding.viewModel = viewModel // XML 中直接绑定 user.name}
}

5. 适用场景

  • MVC:快速原型开发或简单页面,不推荐复杂项目。

  • MVP:需要高测试覆盖率的项目(Presenter 可独立测试)。

  • MVVM:中大型项目,结合 Jetpack 组件(推荐 Google 官方方案)。


6. 总结

维度MVCMVPMVVM
代码耦合度高(Controller 臃肿)低(通过接口解耦)低(数据驱动)
测试难度困难容易(Presenter 可单元测试)容易(ViewModel 可测试)
维护性较好优秀
学习曲线简单中等中等(需 Jetpack 知识)

 

7. 现代 Android 开发推荐

  • 优先选择 MVVM:结合 Jetpack 组件(ViewModel + LiveData + DataBinding/Room)实现高效开发。

  • 辅助工具

    • Dagger/Hilt:依赖注入,进一步解耦。

    • Jetpack Compose:声明式 UI,天然适合 MVVM。

通过理解这三种架构的核心差异,开发者可以更合理地选择适合项目需求的模式。对于新项目,强烈建议采用 MVVM + Jetpack 的现代化架构方案。


http://www.ppmy.cn/server/174573.html

相关文章

SVN 拉取,文件冲突 解决办法

情景 svn 在拉取代码时 提示 已跳过&#xff0c;其余有冲突 &#xff0c;警告至少还有一个的文件处于冲突状态 导致文件拉取失败 一、原因 版本库和本地工作副本之间存在文件冲突&#xff0c;导致文件无法正常拉取。 二、 Terminal 窗口解决办法 1.查看冲突文件 在 Termin…

关于AI数据分析可行性的初步评估

一、结论&#xff1a;可在部分环节嵌入&#xff0c;无法直接处理大量数据 1.非本地部署的AI应用处理非机密文件没问题&#xff0c;内部文件要注意数据安全风险。 2.AI&#xff08;指高规格大模型&#xff09;十分适合探索性研究分析&#xff0c;对复杂报告无法全流程执行&…

已安装 MFC 仍提示“此项目需要 MFC 库”的解决方法 (MSB8041)

编译报错信息表明项目需要 MFC 库&#xff0c;但 Visual Studio 无法找到。尽管你已确认安装了 MFC&#xff0c;问题仍然存在&#xff0c;这通常是由于环境中存在多个 MSVC 版本造成的冲突。 问题描述&#xff1a; 编译时出现错误&#xff1a;error MSB8041: 此项目需要 MFC …

【WRF模拟】如何查看 WPS 的输入静态地理数据(二进制格式)?

查看 WPS 的输入静态地理数据方法总结 方法 1:使用 gdal_translate 将二进制数据转换为 GeoTIFFgdal_translate 工具概述使用 gdal_translate 将二进制数据转换为 GeoTIFF方法 2:使用 ncdump 查看 geo_em.dXX.nc方法 3:使用 Python xarray + matplotlib 可视化 geo_em.dXX.n…

halcon机器人视觉(四)calibrate_hand_eye_stationary_3d_sensor

目录 一、准备数据和模型二、按照表面匹配的的结果进行手眼标定三、根据标定结果计算CalObjInCamPose 一、准备数据和模型 1、读3D模型&#xff1a;read_object_model_3d 2、创建表面匹配模板&#xff1a;create_surface_model 3、创建一个HALCON校准数据模型&#xff1a;crea…

STM32步进电机S型与T型加减速算法

目录 一、基本原理 二、常见类型 三、算法详解 四、应用场合 五、代码实现 1、main

运算符在C和C++中的用法和区别(简洁易懂版)

用法&#xff1a; 在C语言和C中&#xff0c;& 运算符有两种主要的用法&#xff1a;按位与运算符和取地址运算符。 1. 按位与运算符&#xff08;Bitwise AND&#xff09; & 作为按位与运算符用于对两个整数进行逐位的“与”操作。每一位上的值如果两个操作数都为 1&…

k8s中的控制器的使用

一 什么是控制器 控制器也是管理pod的一种手段 自主式pod&#xff1a;pod退出或意外关闭后不会被重新创建 控制器管理的 Pod&#xff1a;在控制器的生命周期里&#xff0c;始终要维持 Pod 的副本数目 Pod控制器是管理pod的中间层&#xff0c;使用Pod控制器之后&#xff0c;…