Bootstrap

Android:MVC、MVP、MVVM模式的详解

在 Android 开发中,MVC(Model-View-Controller)、MVP(Model-View-Presenter)和 MVVM(Model-View-ViewModel)是三种常见的架构模式。每种模式都有其独特的优缺点和适用场景。以下分别通过结构、工作流程、优缺点,对这三种模式详细比较和解释的整理。

1. MVC(Model-View-Controller)

结构
  • Model: 负责应用程序的数据和业务逻辑。
  • View: 负责显示数据(UI),并向用户展示信息。
  • Controller: 处理用户输入,更新 Model 和 View。
工作流程
  1. 用户与 View 交互(例如,点击按钮)。
  2. View 将用户输入传递给 Controller。
  3. Controller 更新 Model。
  4. Model 通知 View 更新(通常通过回调或观察者模式)。
优点
  • 简单易懂,适合小型应用。
  • 直接的用户交互和数据更新。
缺点
  • 随着应用复杂度增加,Controller 可能变得臃肿。
  • View 和 Controller 之间的耦合度较高。
  • MVC 示例中,Activity 直接与 Model 和 View 交互,适合简单的应用。
MVC 示例:

在 MVC 模式中,Activity 充当 Controller,负责与 Model 和 View 交互。

// Model
class CounterModel {
    var count: Int = 0
}

// MainActivity (Controller)
class MainActivity : AppCompatActivity() {
    private lateinit var model: CounterModel

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

        model = CounterModel()
        val countTextView: TextView = findViewById(R.id.countTextView)
        val incrementButton: Button = findViewById(R.id.incrementButton)

        incrementButton.setOnClickListener {
            model.count++
            countTextView.text = "Current Count: ${model.count}"
        }
    }
}

布局文件 (res/layout/activity_main.xml):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center">

    <TextView
        android:id="@+id/countTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Current Count: 0"
        android:textSize="24sp" />

    <Button
        android:id="@+id/incrementButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Increment" />
</LinearLayout>
  • MVC 示例中,Activity 直接与 Model 和 View 交互,适合简单的应用。

2. MVP(Model-View-Presenter)

结构
  • Model: 负责数据和业务逻辑。
  • View: 负责 UI 显示,通常是一个接口。
  • Presenter: 处理用户输入,更新 Model 和 View。
工作流程
  1. 用户与 View 交互。
  2. View 将用户输入传递给 Presenter。
  3. Presenter 更新 Model。
  4. Model 通知 Presenter 数据变化。
  5. Presenter 更新 View。
优点
  • View 和 Presenter 之间的解耦,便于单元测试。
  • Presenter 可以处理复杂的业务逻辑。
缺点
  • 需要编写额外的接口和实现,增加了代码量。
  • 可能导致 Presenter 变得复杂。
MVP 示例:

在 MVP 模式中,Presenter 负责处理业务逻辑,View 只负责显示。

// Model
class CounterModel {
    var count: Int = 0
}

// View Interface
interface CounterView {
    fun displayCount(count: Int)
}

// Presenter
class CounterPresenter(private val view: CounterView, private val model: CounterModel) {
    fun incrementCount() {
        model.count++
        view.displayCount(model.count)
    }
}

// MainActivity (View)
class MainActivity : AppCompatActivity(), CounterView {
    private lateinit var presenter: CounterPresenter
    private lateinit var countTextView: TextView

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

        countTextView = findViewById(R.id.countTextView)
        presenter = CounterPresenter(this, CounterModel())

        val incrementButton: Button = findViewById(R.id.incrementButton)
        incrementButton.setOnClickListener {
            presenter.incrementCount()
        }
    }

    override fun displayCount(count: Int) {
        countTextView.text = "Current Count: $count"
    }
}

布局文件 (res/layout/activity_main.xml):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center">

    <TextView
        android:id="@+id/countTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Current Count: 0"
        android:textSize="24sp" />

    <Button
        android:id="@+id/incrementButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Increment" />
</LinearLayout>
  • MVP 示例中,Presenter 处理业务逻辑,View 只负责显示,适合中等复杂度的应用。

3. MVVM(Model-View-ViewModel)

结构
  • Model: 负责数据和业务逻辑。
  • View: 负责 UI 显示,通常是 Activity 或 Fragment。
  • ViewModel: 处理 UI 相关的数据,负责与 Model 交互。
工作流程
  1. 用户与 View 交互。
  2. View 通过数据绑定或观察者模式与 ViewModel 交互。
  3. ViewModel 更新 Model。
  4. Model 通知 ViewModel 数据变化。
  5. ViewModel 更新 View(通过 LiveData 或其他观察者模式)。
优点
  • 数据绑定简化了 UI 更新。
  • View 和 ViewModel 之间的解耦,便于测试。
  • 更好的支持异步操作和数据流。
缺点
  • 学习曲线较陡,特别是对于数据绑定。
  • 可能导致 ViewModel 变得复杂。
MVVM 示例:

在 MVVM 模式中,ViewModel 负责处理 UI 相关的数据,使用 LiveData 来观察数据变化。

// Model
class CounterModel {
    var count: Int = 0
}

// ViewModel
class CounterViewModel : ViewModel() {
    private val model = CounterModel()
    val countLiveData = MutableLiveData<Int>()

    fun incrementCount() {
        model.count++
        countLiveData.value = model.count
    }
}

// MainActivity (View)
class MainActivity : AppCompatActivity() {
    private lateinit var viewModel: CounterViewModel
    private lateinit var countTextView: TextView

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

        countTextView = findViewById(R.id.countTextView)
        viewModel = ViewModelProvider(this).get(CounterViewModel::class.java)

        viewModel.countLiveData.observe(this, Observer { count ->
            countTextView.text = "Current Count: $count"
        })

        val incrementButton: Button = findViewById(R.id.incrementButton)
        incrementButton.setOnClickListener {
            viewModel.incrementCount()
        }
    }
}

布局文件 (res/layout/activity_main.xml):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center">

    <TextView
        android:id="@+id/countTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Current Count: 0"
        android:textSize="24sp" />

    <Button
        android:id="@+id/incrementButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Increment" />
</LinearLayout>
  • MVVM 示例中,ViewModel 使用 LiveData 观察数据变化,适合现代 Android 开发,特别是与 Jetpack 组件结合使用。

总结

  • MVC 适合小型应用,简单易懂,但在复杂应用中可能导致 Controller 过于臃肿。
  • MVP 提供了更好的解耦和可测试性,适合中型应用,但需要更多的代码结构。
  • MVVM 是现代 Android 开发的推荐模式,特别是与 Jetpack 组件(如 LiveData 和 ViewModel)结合使用时,能够提供更好的数据管理和 UI 更新机制。

选择哪种模式取决于你的应用需求、团队的熟悉程度以及项目的复杂性。

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;