移动应用架构设计:MVVM实战教程(零基础友好)

Swagger抄写员
2025-06-21 23:10
阅读 458

一、开篇:什么是MVVM?它用来做什么?

一、开篇:什么是MVVM?它用来做什么?

在移动开发中,我们常常会遇到一个问题:“代码写得很乱,后期很难维护。”

为了避免这种情况,开发者们总结出了一套结构清晰、易于扩展的开发方式,叫做 架构设计模式。今天我们要学习的 MVVM(Model-View-ViewModel),就是目前最流行的一种架构模式。

简单理解 MVVM 的三个部分:

层级 中文名 作用
Model 数据层 处理数据相关逻辑(比如从服务器取数据)
View 视图层 用户看得到的部分(比如按钮、文字)
ViewModel 视图模型 连接数据和视图,处理业务逻辑

💡 为什么用 MVVM?

  • 清晰分离关注点(各司其职)
  • 更容易测试代码
  • 后期维护成本低

二、环境准备:搭建你的开发环境

二、环境准备:搭建你的开发环境

移动应用界面设计-2

⚠️ 假设你已经安装了 Android Studio。如果没有,请先去官网下载并安装。

步骤 1:创建一个新项目

  1. 打开 Android Studio
  2. 点击 New Project
  3. 选择模板:Empty Activity
  4. 项目名称:MVVMExample
  5. 语言选择:✅ Kotlin(更推荐)、Java 也可以
  6. 完成创建

步骤 2:添加 Jetpack 库支持(Google 官方推荐)

打开 build.gradle (Module: app) 文件,在 dependencies{} 中加入以下依赖:

// Lifecycle & ViewModel 支持
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1'

// Room 数据库支持(可选)
implementation "androidx.room:room-runtime:2.5.2"
kapt "androidx.room:room-compiler:2.5.2"

// Retrofit 网络请求(可选)
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

然后点击 Sync Now 同步构建。

📌 新手小贴士

  • 如果遇到同步失败,检查网络连接或尝试使用科学上网工具。
  • 初学时可以先不加 Room 和 Retrofit,后面再逐步加入。

三、核心概念讲解(结合代码示例)

我们通过一个简单的 App 来理解 MVVM,App 功能是显示一段文本:“Hello, MVVM!”。

3.1 Model 层(数据层)

我们模拟一个数据源,返回字符串内容。

步骤:

  1. 新建包:model
  2. 创建类 TextRepository.kt
class TextRepository {
    fun getWelcomeText(): String {
        return "Hello, MVVM!"
    }
}

📌 解释

  • Repository 是数据来源的封装,它可以来自网络、数据库、本地等。
  • 这里为了简单起见,直接返回一个静态字符串。

3.2 ViewModel 层(视图模型)

ViewModel 担任 View 和 Model 之间的桥梁。

步骤:

  1. 新建包:viewmodel
  2. 添加类 MainViewModel.kt
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch

class MainViewModel : ViewModel() {

    private val repository = TextRepository()

    // 使用 liveData 分发数据给视图
    val welcomeText = repository.getWelcomeText()
}

📌 解释

  • ViewModel 类继承自 ViewModel,生命周期与页面绑定。
  • viewModelScope 是协程作用域,方便做异步操作(例如联网请求)。

3.3 View 层(用户界面)

View 就是我们看到的界面 UI。在 Android 中通常是一个 ActivityFragment

步骤:

修改 activity_main.xml 文件:

<TextView
    android:id="@+id/tv_welcome"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="24sp"
    android:layout_centerInParent="true"/>

接下来修改 MainActivity.kt 文件:

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider

class MainActivity : AppCompatActivity() {

    private lateinit var viewModel: MainViewModel

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

        // 获取 TextView 控件
        val textView = findViewById<TextView>(R.id.tv_welcome)

        // 初始化 ViewModel
        viewModel = ViewModelProvider(this).get(MainViewModel::class.java)

        // 显示数据
        textView.text = viewModel.welcomeText
    }
}

📌 解释

  • ViewModelProvider 用于获取或创建 ViewModel 实例。
  • 这样即使屏幕旋转,数据也不会丢失。

四、实战项目:做一个“随机笑话生成器”

我们来做一个更有意思的小项目 —— 随机笑话生成器!每次点击按钮就换一个新的笑话。

4.1 需求分析

  • 显示一句话笑话
  • 有个按钮“换一个”
  • 笑话由 ViewModel 提供
  • 笑话存储在 Repository 中

4.2 修改 Model(增加笑话数据)

新建 JokeRepository.kt

class JokeRepository {
    private val jokes = listOf(
        "程序员最爱的一首歌:Ctrl+C Ctrl+V",
        "我跟老板说我想休假……他说‘好啊,那工资自动清零’。",
        "程序员不会死,只是内存泄漏了。",
        "今天去面试Android工程师,结果让我讲个笑话…我说了一个叫MVVM。",
        "没有 Bug 的代码,就像没有空气的地球——根本活不了!"
    )

    fun getRandomJoke(): String {
        return jokes.random()
    }
}

4.3 修改 ViewModel(新增方法)

修改 MainViewModel.kt

class MainViewModel : ViewModel() {
    private val repository = JokeRepository()

    fun getRandomJoke(): String {
        return repository.getRandomJoke()
    }
}

4.4 修改布局文件(activity_main.xml)

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

    <TextView
        android:id="@+id/tv_joke"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:padding="16dp"
        android:text="这里显示笑话"/>

    <Button
        android:id="@+id/btn_new_joke"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="换一个"/>
</LinearLayout>

4.5 修改 MainActivity.kt

class MainActivity : AppCompatActivity() {
    private lateinit var viewModel: MainViewModel
    private lateinit var tvJoke: TextView
    private lateinit var btnNewJoke: Button

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

        tvJoke = findViewById(R.id.tv_joke)
        btnNewJoke = findViewById(R.id.btn_new_joke)
        viewModel = ViewModelProvider(this).get(MainViewModel::class.java)

        // 初始加载一个笑话
        tvJoke.text = viewModel.getRandomJoke()

        // 按钮点击事件
        btnNewJoke.setOnClickListener {
            tvJoke.text = viewModel.getRandomJoke()
        }
    }
}

运行一下看看效果吧!


五、常见问题解答(FAQ)

应用性能监控-1

❓ Q1:MVVM 和 MVP 是什么关系?哪个更好?

  • MVP(Model-View-Presenter) 是早期流行的结构模式,Presenter 与 View 强关联。
  • MVVM 更适合数据驱动的场景,尤其是配合 LiveData/StateFlow 使用非常灵活。
  • 对初学者来说,MVVM + Jetpack 架构组件 是目前 Android 主流做法,建议优先掌握。

❓ Q2:ViewModel 只能在 Activity 中使用吗?能不能在 Fragment 中用?

  • 当然可以在 Fragment 中使用。
  • 调用方式一样:
val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)

区别在于传入的上下文(this)。Fragment 中 this 指的是 Fragment 自己。


❓ Q3:LiveData 是什么?一定要用吗?

  • LiveData 是一种可观察的数据持有者,它能感知生命周期。
  • 当前页面不可见(比如后台)时,不会更新 UI,防止内存泄漏。
  • 初学阶段可以直接暴露为普通变量,但建议尽早熟悉 LiveData。

❓ Q4:如何测试 ViewModel 中的逻辑?

  • 可以使用 JUnit 单元测试 ViewModel。
  • 举例:
@Test
fun testRandomJokeNotEmpty() {
    val viewModel = MainViewModel()
    val joke = viewModel.getRandomJoke()
    assertTrue(joke.isNotEmpty())
}

📌 推荐在 Gradle 配置中加入 testImplementation 'junit:junit:4.13.2'


六、下一步学习建议

恭喜你完成了第一个基于 MVVM 架构的 App!

接下来你可以继续深入学习以下几个方向:

🧩 1. 加入网络请求(Retrofit + Coroutines)

  • 学习使用 Retrofit 请求 API
  • 结合 ViewModelLiveData 显示远程数据

🧩 2. 使用 Room 数据库持久化

  • 学习本地数据库保存数据
  • 如笑话收藏功能

🧩 3. 引入 Navigation 组件简化页面跳转

  • 使用 Jetpack Navigation 管理页面导航
  • 有助于构建复杂 App

🧩 4. 理解 Clean Architecture 分层思想

  • 分清不同层级的责任边界
  • 项目结构更规范,利于长期维护

🧩 5. 学习 Compose + MVVM 结合

  • Android 最新的 UI 框架 Jetpack Compose
  • 与 MVVM 配合也非常棒

总结

本文带你从零开始认识并实践了 MVVM 架构,通过一个“随机笑话生成器”项目的完整实现,了解了 MVVM 的三大组成部分:

  • Model(数据层)
  • ViewModel(数据与 UI 交互中心)
  • View(UI 层)

希望你能动手跟着写一遍,边学边练才记得牢。

如果你愿意继续深入学习,欢迎查看我们的下一讲《高级 MVVM 技术:搭配 Retrofit 与 LiveData》。

Happy coding! 🚀


作者简介:一位深耕 Android 教育多年的讲师,专注帮助编程小白快速入门,擅长将复杂知识拆解为通俗易懂的例子。欢迎关注我的博客与课程系列,一起成为更好的开发者!

评论 0

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