移动应用架构设计:MVVM实战

写码的阿川
2025-06-27 20:19
阅读 579

开篇:什么是 MVVM?我们为什么要学它?

开篇:什么是 MVVM?我们为什么要学它?

在开发移动应用的过程中,代码结构的清晰与否直接影响到项目的可维护性和扩展性。MVVM(Model-View-ViewModel)是一种常用于 Android 和 iOS 应用开发的架构模式,它的核心思想是将界面显示与数据逻辑分离

简单来说,MVVM 分为三个部分:

  1. View(视图):用户看到的界面,比如按钮、文本框等。
  2. ViewModel(视图模型):处理逻辑的地方,不直接接触 View。
  3. Model(模型):负责数据存储和管理,比如数据库或网络请求。

学习 MVVM 的好处:

  • 代码更容易维护
  • 更容易进行单元测试
  • 界面和逻辑分离,便于多人协作开发

现在我们从零开始,一起完成一个简单的项目,深入理解 MVVM 模式的工作原理。


环境准备:Android Studio 配置指南

环境准备:Android Studio 配置指南

你需要以下工具来跟着本教程操作:

✅ 安装 Android Studio

  1. 前往 Android Studio官网 下载安装包;
  2. 安装完成后打开软件,选择 "New Project" 创建新项目;
  3. 选择模板 “Empty Activity”,点击 Next;
  4. 设置项目名:MyMvvmApp,语言选择 Kotlin,点击 Finish。

原生应用架构-1

✅ 添加依赖项

打开 build.gradle (Module: app) 文件,添加如下依赖(确保版本号最新):

dependencies {
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
    implementation "androidx.activity:activity-ktx:1.7.2"
}

同步 Gradle 后,环境就准备好了!


核心概念详解

我们先了解 MVVM 中每个组成部分的具体含义,并配合最简单的例子说明。

📌 1. Model 层:处理数据

这是你的“业务核心”。比如你做一个天气预报 App,那么 Model 就是获取和解析天气数据的部分。

举个例子:

class UserRepository {
    fun getUsername(): String {
        return "Hello MVVM User!"
    }
}

这个 UserRepository 类就是一个 Model,它模拟了读取用户名的操作。

📌 2. ViewModel 层:连接桥梁

ViewModel 是 View 和 Model 之间的中介,它可以保存 UI 数据,在配置变化时也保持状态(如屏幕旋转不会丢失数据)。

创建一个 ViewModel:

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class UserViewModel : ViewModel() {
    private val repository = UserRepository()

    private val _username = MutableStateFlow("")
    val username: StateFlow<String> = _username

    fun loadUsername() {
        viewModelScope.launch {
            _username.value = repository.getUsername()
        }
    }
}

这段代码中,viewModelScope 是协程作用域,保证任务在 ViewModel 生命周期内执行。

📌 3. View 层:UI 显示

View 是你在布局文件中写的页面,比如 XML 中的 TextView,以及 Activity/Fragment 中控制它们的部分。

例如修改 activity_main.xml

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Loading..."
    android:textSize="20sp"/>

然后在 MainActivity.kt 中绑定 ViewModel:

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.viewModels
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.runBlocking

class MainActivity : AppCompatActivity() {
    private val viewModel: UserViewModel by viewModels()

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

        val textView = findViewById<TextView>(R.id.textView)

        // 观察 username 变化
        runBlocking {
            viewModel.username.collect { name ->
                textView.text = name
            }
        }

        viewModel.loadUsername()
    }
}

这样我们完成了 MVVM 的基本三部分联动!


实战项目:一个简单的用户名展示 App

我们将实现一个功能:点击按钮后,显示从 Model 获取的用户名。

步骤 1️⃣:修改布局文件

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

    <TextView
        android:id="@+id/tv_username"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="等待加载"
        android:textSize="18sp"/>


![应用性能监控-2](https://code-guide.oss.shanghai.autogptai.club/common/file/download?name=date2025062720/123f1269-a297-45f6-ba57-16499ccce6ed.jpg)


    <Button
        android:id="@+id/btn_load"
        android:layout_marginTop="16dp"
        android:text="加载用户名"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

步骤 2️⃣:更新 ViewModel

我们稍作修改,让 ViewModel 在接收到点击事件后才去加载数据。

fun loadUsername() {
    viewModelScope.launch {
        _username.value = repository.getUsername()
    }
}

这个函数会被调用时启动协程去获取用户名。

步骤 3️⃣:更新 MainActivity

class MainActivity : AppCompatActivity() {

    private val viewModel: UserViewModel by viewModels()
    private lateinit var tvName: TextView
    private lateinit var btnLoad: Button

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

        tvName = findViewById(R.id.tv_username)
        btnLoad = findViewById(R.id.btn_load)

        btnLoad.setOnClickListener {
            viewModel.loadUsername()
        }

        lifecycleScope.launch {
            viewModel.username.collect { name ->
                tvName.text = name
            }
        }
    }
}

这里我们使用了 lifecycleScope 来监听 ViewModel 的用户名变化并更新 UI。

✅ 到此为止,一个完整的 MVVM 架构的小型 App 就完成啦!


新手常见问题解答 ⚠️

Q1:ViewModel 怎么跟 Activity 或 Fragment 联系起来?

A:通过 by viewModels() 来获取,系统会帮你管理生命周期。


Q2:为什么不能在 ViewModel 里直接操作 UI?

A:MVVM 的原则就是 数据逻辑与 UI 解耦合。ViewModel 不持有 View 的引用,避免内存泄漏和紧耦合。


Q3:什么是 LiveData?和 Flow 有什么区别?

A:LiveDataFlow 都是用来观察数据变化的组件。LiveData 是基于生命周期感知的回调方式,而 Flow 是 Kotlin 协程下的响应式编程方式。本教程使用的是 Flow + ViewModel 组合的方式。


Q4:ViewModel 里的数据会不会在横竖屏切换时丢掉?

A:不会!ViewModel 是设计用来在配置更改(如屏幕旋转)中保持状态的。


Q5:能不能多个 View 共享同一个 ViewModel?

A:可以!通过 by activityViewModels() 让多个 Fragment 共享同一个 ViewModel。


学习建议:下一步你可以做什么?

掌握了 MVVM 的基础之后,推荐继续学习这些内容来拓展知识边界:

🔹 进阶技能推荐:

  1. Room 持久化数据库(Model层)
  2. Retrofit & Ktor 网络请求(Model层)
  3. Navigation Component 导航组件(View层)
  4. Koin / Dagger / Hilt 依赖注入框架(提升代码解耦能力)
  5. Unit Test & Instrumented Test(增强测试能力)

📚 推荐学习路径:

  1. 复写今天的内容,试着把“用户名”换成“随机笑话”、“天气信息”等;
  2. 把本地数据改成从网络接口拿;
  3. 尝试封装 Repository,统一管理 Model;
  4. 使用 Jetpack Compose 编写现代 UI,替代传统 XML 方式;
  5. 最终目标:完成一个完整项目(如 Todo List、博客阅读器等),用 MVVM 全流程架构实现。

总结

本文带领大家从零开始,实践了一个基于 MVVM 架构的 Android 应用程序。我们学习了:

  • MVVM 的三层结构及各自职责;
  • 如何在 Android 项目中搭建 MVVM 的基础架构;
  • 实现了从按钮点击 -> 加载数据 -> 更新界面的完整流程;
  • 解答了新手常见的疑问。

只要你愿意动手练习,不断调试与重构,MVVM 并不难掌握。希望这篇教程能成为你走向专业 Android 开发的第一步!

🎉 Happy Coding,MVVM Start Now!

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝