32 进阶主题之MVVM架构

在上一章中,我们深入探讨了Android Jetpack组件,这为我们的应用开发提供了强大的支持。在本章中,我们将讨论如何运用MVVM架构来构建可维护和可扩展的Android应用。

什么是MVVM架构?

MVVM(Model-View-ViewModel)是一种软件设计模式,分离了用户界面逻辑和业务逻辑。在这个模式中:

  • Model:代表应用的数据模型,包括数据结构和业务逻辑。
  • View:是用户界面,负责显示数据并将用户的输入传递给ViewModel。
  • ViewModel:作为View和Model之间的中介,处理与UI相关的逻辑,并将数据提供给View。

MVVM的优点

  1. 分离关注点:使得代码更清晰,易于维护。
  2. 可测试性:通过抽象化View和Model,便于对业务逻辑进行单元测试。
  3. 增强的可重用性:View和ViewModel的独立性使得它们可以被重用。

MVVM在Android中的实现

为了实现MVVM架构,我们通常会使用Android的ViewModelLiveData。在这里,我们将通过一个简单的ToDo List应用示例,演示MVVM架构的实现。

1. 创建数据模型

首先,我们需要创建一个简单的ToDo数据模型。

1
2
3
4
5
data class ToDo(
val id: Int,
val task: String,
var isCompleted: Boolean
)

2. 创建ViewModel

接下来,我们创建一个ViewModel来承载我们的UI逻辑和数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class ToDoViewModel : ViewModel() {
private val _toDoList = MutableLiveData<List<ToDo>>()

val toDoList: LiveData<List<ToDo>>
get() = _toDoList

init {
// 初始化数据
_toDoList.value = listOf(
ToDo(1, "学习MVVM", false),
ToDo(2, "更新个人简历", false),
ToDo(3, "去超市购物", false)
)
}

fun toggleComplete(toDo: ToDo) {
val currentList = _toDoList.value ?: return
val updatedList = currentList.map {
if (it.id == toDo.id) it.copy(isCompleted = !it.isCompleted) else it
}
_toDoList.value = updatedList
}
}

3. 创建View

在我们的Activity或Fragment中,我们将观察ViewModel中的数据,并通过UI更新视图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

class MainActivity : AppCompatActivity() {
private val viewModel: ToDoViewModel by viewModels()
private lateinit var recyclerView: RecyclerView
private lateinit var adapter: ToDoAdapter

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

recyclerView = findViewById(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
adapter = ToDoAdapter { toDo ->
viewModel.toggleComplete(toDo)
}
recyclerView.adapter = adapter

// 观察toDoList数据变化
viewModel.toDoList.observe(this, Observer { toDoList ->
adapter.submitList(toDoList)
})
}
}

4. 创建RecyclerView适配器

我们需要一个适配器来将ToDo列表显示在RecyclerView中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView

class ToDoAdapter(private val onClick: (ToDo) -> Unit) :
ListAdapter<ToDo, ToDoAdapter.ToDoViewHolder>(ToDoDiffCallback()) {

class ToDoViewHolder(itemView: View, val onClick: (ToDo) -> Unit) : RecyclerView.ViewHolder(itemView) {
private val taskTextView: TextView = itemView.findViewById(R.id.taskTextView)

fun bind(toDo: ToDo) {
taskTextView.text = toDo.task
itemView.setOnClickListener { onClick(toDo) }
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ToDoViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_todo, parent, false)
return ToDoViewHolder(view, onClick)
}

override fun onBindViewHolder(holder: ToDoViewHolder, position: Int) {
holder.bind(getItem(position))
}
}

class ToDoDiffCallback : DiffUtil.ItemCallback<ToDo>() {
override fun areItemsTheSame(oldItem: ToDo, newItem: ToDo): Boolean {
return oldItem.id == newItem.id
}

override fun areContentsTheSame(oldItem: ToDo, newItem: ToDo): Boolean {
return oldItem == newItem
}
}

5. 布局文件

activity_main.xml中,我们需要设置RecyclerView。

1
2
3
4
5
6
7
8
9
10
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

item_todo.xml中,我们可以定义每个任务的布局。

1
2
3
4
5
6
7
8
9
10
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">

<TextView
android:id="@+id/taskTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

小结

通过本章的学习,我们了解了MVVM架构的基本原理及其在Android中的实际应用。我们创建了一个简单的ToDo List应用,演示了如何使用ViewModelLiveData来实现数据的观察与更新。

在下一章中,我们将探索如何

32 进阶主题之MVVM架构

https://zglg.work/android-app-dev/32/

作者

IT教程网(郭震)

发布于

2024-08-14

更新于

2024-08-15

许可协议

分享转发

交流

更多教程加公众号

更多教程加公众号

加入星球获取PDF

加入星球获取PDF

打卡评论