在上一章中,我们深入探讨了Android Jetpack组件,这为我们的应用开发提供了强大的支持。在本章中,我们将讨论如何运用MVVM
架构来构建可维护和可扩展的Android应用。
什么是MVVM架构?
MVVM
(Model-View-ViewModel)是一种软件设计模式,分离了用户界面逻辑和业务逻辑。在这个模式中:
- Model:代表应用的数据模型,包括数据结构和业务逻辑。
- View:是用户界面,负责显示数据并将用户的输入传递给ViewModel。
- ViewModel:作为View和Model之间的中介,处理与UI相关的逻辑,并将数据提供给View。
MVVM的优点
- 分离关注点:使得代码更清晰,易于维护。
- 可测试性:通过抽象化View和Model,便于对业务逻辑进行单元测试。
- 增强的可重用性:View和ViewModel的独立性使得它们可以被重用。
MVVM在Android中的实现
为了实现MVVM架构,我们通常会使用Android的ViewModel
和LiveData
。在这里,我们将通过一个简单的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
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
应用,演示了如何使用ViewModel
和LiveData
来实现数据的观察与更新。
在下一章中,我们将探索如何