五分钟快速了解MVI、MVVM、MVP

MVI、MVVM、MVP 介绍与区别

在 Android 开发中,MVIMVVMMVP 是三种常见的架构模式。它们主要用于 分离 UI 和业务逻辑 ,提高代码的 可维护性可测试性


1️⃣ MVP(Model-View-Presenter)

📌 介绍

MVP 是一种较早的架构模式,主要将 ViewModel 解耦,并通过 Presenter 作为中间层。

  • View(界面层):Activity / Fragment,负责 UI 交互。
  • Presenter(业务逻辑层):处理业务逻辑,并通知 View 更新 UI。
  • Model(数据层):负责数据操作,例如数据库、网络请求等。

📌 核心思想View 只负责 UI 展示,Presenter 负责逻辑处理,Model 提供数据。


📝 示例

1️⃣ 创建 Model(数据层)
kotlin 复制代码
interface LoginModel {
    fun login(username: String, password: String, callback: (Boolean) -> Unit)
}

class LoginModelImpl : LoginModel {
    override fun login(username: String, password: String, callback: (Boolean) -> Unit) {
        callback(username == "admin" && password == "1234") // 简单模拟
    }
}
2️⃣ 创建 View(UI 层接口)
kotlin 复制代码
interface LoginView {
    fun showLoading()
    fun hideLoading()
    fun showLoginSuccess()
    fun showLoginError()
}
3️⃣ 创建 Presenter(业务逻辑层)
kotlin 复制代码
class LoginPresenter(private val view: LoginView, private val model: LoginModel) {
    fun onLoginClicked(username: String, password: String) {
        view.showLoading()
        model.login(username, password) { isSuccess ->
            view.hideLoading()
            if (isSuccess) view.showLoginSuccess() else view.showLoginError()
        }
    }
}
4️⃣ 在 Activity 中实现 LoginView
kotlin 复制代码
class LoginActivity : AppCompatActivity(), LoginView {
    private lateinit var presenter: LoginPresenter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        presenter = LoginPresenter(this, LoginModelImpl())

        findViewById<Button>(R.id.login_button).setOnClickListener {
            presenter.onLoginClicked("admin", "1234")
        }
    }

    override fun showLoading() { /* 显示加载动画 */ }
    override fun hideLoading() { /* 隐藏加载动画 */ }
    override fun showLoginSuccess() { Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show() }
    override fun showLoginError() { Toast.makeText(this, "登录失败", Toast.LENGTH_SHORT).show() }
}

✅ 优势

解耦 UI 和逻辑View 只负责 UI,Presenter 处理业务逻辑。

Presenter 可单独测试,提高可测试性。

❌ 缺点

Presenter 可能变得很大 ,随着功能增加,可能导致 Presenter 代码臃肿。


2️⃣ MVVM(Model-View-ViewModel)

📌 介绍

MVVM 由 Google 官方推荐,借助 LiveDataStateFlow 进行数据绑定,使 ViewModel 持有数据并驱动 UI。

  • Model(数据层):负责数据操作。
  • ViewModel(逻辑层):负责数据处理,使用 LiveData/StateFlowView 观察数据变化。
  • View(界面层):Activity / Fragment,观察 ViewModel 并更新 UI。

📌 核心思想View 监听 ViewModel 的数据变化,数据驱动 UI。


📝 示例

1️⃣ 创建 ViewModel
kotlin 复制代码
class LoginViewModel : ViewModel() {
    private val _loginResult = MutableLiveData<Boolean>()
    val loginResult: LiveData<Boolean> get() = _loginResult

    fun login(username: String, password: String) {
        _loginResult.value = (username == "admin" && password == "1234") // 模拟登录
    }
}
2️⃣ 在 Activity 中观察 ViewModel
kotlin 复制代码
class LoginActivity : AppCompatActivity() {
    private lateinit var viewModel: LoginViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        viewModel = ViewModelProvider(this)[LoginViewModel::class.java]

        findViewById<Button>(R.id.login_button).setOnClickListener {
            viewModel.login("admin", "1234")
        }

        viewModel.loginResult.observe(this) { isSuccess ->
            if (isSuccess) Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show()
            else Toast.makeText(this, "登录失败", Toast.LENGTH_SHORT).show()
        }
    }
}

✅ 优势

ViewModel 生命周期安全 ,不会因 Activity 旋转而丢失数据。

View 只监听数据变化,减少 UI 层代码

数据驱动 UI,逻辑更清晰。

❌ 缺点

LiveData 可能导致内存泄漏 (如果没有正确清理)。

数据流动较隐式,初学者可能不容易理解。


3️⃣ MVI(Model-View-Intent)

📌 介绍

MVI 采用 单向数据流View 触发 Intent(用户意图),ViewModel 处理后更新 State(状态),然后 View 监听 State 变化。

  • Model(数据层):提供数据。
  • View(界面层):监听 State 并更新 UI。
  • Intent(用户意图):用户的操作,如点击按钮。
  • State(状态):ViewModel 维护的 UI 状态,View 观察它。

📌 核心思想 :UI 由 State 驱动,所有事件是单向的,确保数据一致性。


📝 示例

1️⃣ 定义 UI 状态
kotlin 复制代码
data class LoginState(val isLoading: Boolean = false, val isSuccess: Boolean? = null)
2️⃣ 创建 ViewModel
kotlin 复制代码
class LoginViewModel : ViewModel() {
    private val _state = MutableStateFlow(LoginState())
    val state: StateFlow<LoginState> get() = _state

    fun login(username: String, password: String) {
        _state.value = LoginState(isLoading = true)
        viewModelScope.launch {
            delay(1000) // 模拟网络请求
            _state.value = LoginState(isSuccess = (username == "admin" && password == "1234"))
        }
    }
}
3️⃣ 在 Activity 中监听状态
kotlin 复制代码
class LoginActivity : AppCompatActivity() {
    private lateinit var viewModel: LoginViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        viewModel = ViewModelProvider(this)[LoginViewModel::class.java]

        lifecycleScope.launch {
            viewModel.state.collect { state ->
                if (state.isLoading) showLoading()
                else if (state.isSuccess == true) showSuccess()
                else showError()
            }
        }
    }
}

✅ 优势

状态管理清晰 ,避免数据不一致。

单向数据流,逻辑更易维护。

❌ 缺点

需要理解 StateFlow / Redux 思想,初学者不易上手。


🔥 总结

架构 适用场景 优势 缺点
MVP 小型项目 解耦 UI 和逻辑 Presenter 可能变大
MVVM 官方推荐 数据驱动 UI 可能导致内存泄漏
MVI 状态驱动 单向数据流,数据一致性好 学习曲线较陡

如果是 现代 Android 开发,推荐 MVVM / MVI 🚀。

相关推荐
selt7916 小时前
Redisson之RedissonLock源码完全解析
android·java·javascript
Yao_YongChao6 小时前
Android MVI处理副作用(Side Effect)
android·mvi·mvi副作用
非凡ghost7 小时前
JRiver Media Center(媒体管理软件)
android·学习·智能手机·媒体·软件需求
席卷全城7 小时前
Android 推箱子实现(引流文章)
android
齊家治國平天下7 小时前
Android 14 系统中 Tombstone 深度分析与解决指南
android·crash·系统服务·tombstone·android 14
maycho1239 小时前
MATLAB环境下基于双向长短时记忆网络的时间序列预测探索
android
思成不止于此10 小时前
【MySQL 零基础入门】MySQL 函数精讲(二):日期函数与流程控制函数篇
android·数据库·笔记·sql·学习·mysql
brave_zhao10 小时前
达梦数据库(DM8)支持全文索引功能,但并不直接兼容 MySQL 的 FULLTEXT 索引语法
android·adb
sheji341610 小时前
【开题答辩全过程】以 基于Android的网上订餐系统为例,包含答辩的问题和答案
android
easyboot11 小时前
C#使用SqlSugar操作mysql数据库
android·sqlsugar