Kotlin 中的架构模式:MVC、MVP、MVVM 和 MVI

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

如何在混乱中保持清醒:Kotlin 中的架构模式



你是否曾经在项目写完一个月后重新打开,却找不到登录逻辑在哪里?或者试图添加一个新按钮,结果却破坏了列表的功能?听起来很熟悉?欢迎来到没有架构的应用世界。



Kotlin 中的架构模式并非追逐时尚,也不是抽象的理论。它们是拯救你于“面条式代码”的良方——那种业务逻辑、UI、网络和数据库操作全都混在一起的代码。在本文中,我们将深入探讨四种主要模式:MVC、MVP、MVVM 和 MVI。你将通过真实的 Kotlin 示例看到它们的实际应用,理解关键区别,并能为你的任务选择正确的工具。我们开始吧!



什么是架构模式,为什么需要它?



架构模式是你应用的骨架。它规定了类之间如何通信、数据存储在哪里、以及谁负责显示。没有它,你迟早会得到一个 God Object——一个什么都做的类。或者陷入 Callback Hell——一个回调引发另一个回调,代码变得难以阅读。



Kotlin 凭借其简洁的语法和空安全性,非常适合构建清晰的架构。但语言只是成功的一半。另一半是正确选择模式。



MVC(Model-View-Controller)——经典之作



这是最古老、最简单的模式。其核心是:

  • Model——数据和业务逻辑。
  • View——显示层(Activity、Fragment、Compose)。
  • Controller——连接层,处理用户输入。


在 Kotlin 中(尤其是 Android 开发),MVC 常常演变成“臃肿的 Controller”。Activity 同时扮演了 View 和 Controller 的角色。例如:



// 糟糕的做法:Activity 既是 View 又是 Controllerclass LoginActivity : AppCompatActivity() {    private lateinit var emailEditText: EditText    private lateinit var passwordEditText: EditText

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

// Controller 逻辑直接写在这里 findViewById<Button>(R.id.loginButton).setOnClickListener { val email = emailEditText.text.toString() val password = passwordEditText.text.toString() // 验证和 API 调用——全在一个地方 if (email.isNotEmpty() && password.isNotEmpty()) { loginUser(email, password) } } }

private fun loginUser(email: String, password: String) { // 网络操作——直接在 Activity 中 CoroutineScope(Dispatchers.IO).launch { val result = api.login(email, password) withContext(Dispatchers.Main) { // UI 更新——也在这里 Toast.makeText(this@LoginActivity, result.message, Toast.LENGTH_SHORT).show() } } }}


优点:简单,入门门槛低。

缺点:View 和 Controller 紧密耦合。没有 Android 模拟器就无法测试逻辑。对于大型项目来说,简直是噩梦。



MVP(Model-View-Presenter)——权力分离



MVP 解决了 MVC 的主要问题:通过接口将 View 与逻辑分离。Presenter 是“大脑”,对 Android 一无所知。View 是被动的中间层。



Kotlin 示例:



// 用于通信的接口interface LoginView {    fun showLoading()    fun hideLoading()    fun showError(message: String)    fun navigateToHome()}

class LoginPresenter(private val view: LoginView, private val authRepository: AuthRepository) {

fun login(email: String, password: String) { view.showLoading() CoroutineScope(Dispatchers.IO).launch {

博客

书籍推荐