Jupyter AI

32 进阶主题之MVVM架构

📅 发表日期: 2024年8月15日

分类: 📱安卓应用开发

👁️阅读: --

在上一章中,我们深入探讨了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数据模型。

data class ToDo(
    val id: Int,
    val task: String,
    var isCompleted: Boolean
)

2. 创建ViewModel

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

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更新视图。

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中。

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。

<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中,我们可以定义每个任务的布局。

<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来实现数据的观察与更新。

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