发布于 

MVVM设计架构浅析

实习时用的是MVP架构,但Google官方本身已经将MVVM(Model-View-ViewModel)MV作为推荐的设计架构,在JetPack当中也推出了一系列组件来支持,简单谈一下我对MVVM的理解

MVVM架构特点

  1. 分离关注点:MVVM 将用户界面的表示(View)与业务逻辑和数据(ViewModel)分离开来,使得代码结构清晰,易于维护和扩展。ViewModel 作为连接 View 和 Model 的中间层,负责处理用户交互和数据绑定。
  2. 双向数据绑定:MVVM 支持双向数据绑定,使得 View 和 ViewModel 之间的数据同步变得简单。当 ViewModel 中的数据发生变化时,自动更新关联的 View,反之亦然。这样可以避免手动更新界面的繁琐操作,提高开发效率。
  3. 响应式编程:MVVM 借助观察者模式和数据绑定,实现了响应式编程的特性。ViewModel 中的数据变化会触发相应的事件或通知,从而更新关联的 View。这种机制使得界面的状态和数据保持同步,并支持实时更新。
  4. 可测试性:由于 MVVM 将业务逻辑从 View 中分离出来,使得 ViewModel 可以独立于界面进行单元测试。通过模拟输入和验证输出,可以方便地对 ViewModel 进行单元测试,保证代码质量和功能正确性。
  5. 可重用性:MVVM 鼓励将界面逻辑与数据逻辑解耦,使得 ViewModel 可以在不同的界面中重复使用。这种可重用性降低了代码的重复编写,提高了开发效率。

总的来说,MVVM 提供了一种结构清晰、可测试、可重用的开发模式,使得开发者可以更好地管理和组织代码,提高开发效率,并改善用户界面的交互和体验。

带来的改变

结合上述特点,说一下我理解的MVVM为Android应用开发带来的改变:

  1. 分离关注点:分离关注点的设计可以减少代码的耦合性,使得开发者可以专注于不同层级的逻辑,提高代码的可读性和可维护性。
  2. 可测试性:由于 ViewModel 是纯逻辑的组件,可以通过模拟输入和验证输出来进行单元测试,验证其功能的正确性。这样可以提高代码质量,降低 bug 出现的概率。
  3. 数据驱动的界面更新:MVVM 采用双向数据绑定机制,实现了数据驱动的界面更新。ViewModel 中的数据变化会自动更新关联的 View,而用户界面上的输入变化也会实时反映到 ViewModel 的数据中。这种机制使得界面的状态和数据保持同步,减少了手动处理界面更新的代码,提高了开发效率。
  4. 解决横竖屏切换问题:MVVM 架构中,ViewModel 负责保存和管理界面的数据状态。在横竖屏切换时,Activity 或 Fragment 可以销毁并重新创建,而 ViewModel 可以保持不变,从而避免了数据的丢失和重复加载。这种方式使得横竖屏切换更加流畅,用户无感知。
  5. 提升代码的可重用性:由于 MVVM 架构将界面逻辑与数据逻辑解耦,使得 ViewModel 可以在不同的界面中重复使用。这种可重用性降低了代码的重复编写,提高了开发效率。

总体而言,采用 MVVM 架构模式可以改善 Android 开发中的代码组织、可维护性、可测试性和用户界面的交互体验,使得开发者能够更好地管理和开发 Android 应用。

典型MVVM样例

在典型的 Android MVVM 架构中,可能包含以下几个关键类:

  1. Model(模型):Model 类表示应用程序的数据模型,通常是实体类或数据访问层。它负责封装数据和提供数据操作的方法,如从数据库或网络获取数据。
  2. View(视图):View 类表示用户界面的可视化部分,通常是 Activity、Fragment 或自定义视图。它负责展示数据、接收用户输入和处理用户界面事件。
  3. ViewModel(视图模型):ViewModel 类是连接 View 和 Model 的中间层。它持有与用户界面相关的数据,并提供方法供 View 层触发业务逻辑和数据操作。ViewModel 通常包含 LiveData 或 RxJava Observables,用于处理数据变化和实现双向数据绑定。
  4. Repository(仓库):Repository 类用于封装数据源的访问逻辑。它可以从本地数据库、网络或其他数据源获取数据,并将数据提供给 ViewModel 层。Repository 的存在可以解耦 ViewModel 层和底层数据源的具体实现。
  5. LiveData(生命周期感知的数据持有者):LiveData 是 Android 架构组件之一,用于在应用程序组件之间进行数据通信。它是一种观察者模式的实现,可以感知生命周期,并确保数据的更新仅在活跃状态下进行。
  6. Data Binding(数据绑定):Data Binding 是 Android 的特性之一,用于在布局文件中直接绑定数据到 View。它通过生成绑定类,将视图和 ViewModel 之间的数据绑定自动化。

这些类是 MVVM 架构的核心组件,每个类负责不同的职责,共同协作实现数据的管理、展示和交互。然而,具体的实现方式可能因开发者和项目需求而有所不同。

下面展示一个简单登录页面的示例代码:

activity_login.xml(布局文件):

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
<layout xmlns:android="http://schemas.android.com/apk/res/android">

<data>
<variable
name="viewModel"
type="com.example.mvvm.LoginViewModel" />
</data>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@={viewModel.username}" />

<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@={viewModel.password}" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Login"
android:onClick="@{viewModel::onLoginButtonClick}" />

</LinearLayout>
</layout>

LoginViewModel.kt(ViewModel):

1
2
3
4
5
6
7
8
9
10
11
12
class LoginViewModel : ViewModel() {
val username = MutableLiveData<String>()
val password = MutableLiveData<String>()

fun onLoginButtonClick() {
val enteredUsername = username.value
val enteredPassword = password.value

// 执行登录逻辑
// ...
}
}

LoginActivity.kt(Activity):

1
2
3
4
5
6
7
8
9
10
11
12
class LoginActivity : AppCompatActivity() {
private lateinit var binding: ActivityLoginBinding
private lateinit var viewModel: LoginViewModel

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_login)
viewModel = ViewModelProvider(this).get(LoginViewModel::class.java)
binding.viewModel = viewModel
binding.lifecycleOwner = this
}
}

在上述代码示例中,布局文件 activity_login.xml 使用了数据绑定,其中的 EditText 和 Button 的文本属性与 ViewModel 的 username 和 password 属性进行双向绑定。ViewModel 类 LoginViewModel 包含了处理登录逻辑的方法和 MutableLiveData 对象用于保存输入的用户名和密码。Activity 类 LoginActivity 在 onCreate() 方法中使用数据绑定设置 ViewModel 和生命周期所有者。

ViewModel的职责

在 MVVM 架构中,业务逻辑通常会放在 ViewModel 类中。ViewModel 作为 View 和 Model 之间的中间层,负责处理用户界面的交互和数据操作。

具体来说,ViewModel 类可以包含以下业务逻辑:

  1. 用户交互处理:ViewModel 可以响应用户的交互操作,例如按钮点击、列表项选择等。当用户与界面进行交互时,ViewModel 可以执行相应的业务逻辑,如验证输入、发起网络请求、处理数据等。
  2. 数据转换和格式化:ViewModel 可以负责将 Model 中的原始数据进行转换和格式化,以满足界面的显示需求。例如,将日期数据转换为特定格式、将数值进行格式化等。
  3. 数据持久化:如果需要将数据保存到本地存储(如数据库),ViewModel 可以负责处理数据的读取和写入操作。它可以与 Repository 层协同工作,从数据源获取数据或将数据存储到数据源中。
  4. 状态管理:ViewModel 可以管理界面的状态,如加载中、错误状态、空数据状态等。它可以维护相关的状态变量,并根据业务逻辑的执行情况更新状态,以便在界面上正确显示相应的状态。

将业务逻辑放在 ViewModel 中有助于将用户界面和业务逻辑分离,使得代码结构更清晰、易于维护,并提供可测试性。同时,View 层只需要关注界面的展示和用户交互,而不需要直接操作数据和执行复杂的业务逻辑。

此外,ViewModel 应该遵循单一职责原则,不应该包含过多的业务逻辑。如果某些业务逻辑比较复杂或耗时,可以考虑将其委托给其他类或使用异步操作。


本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 @tsparrot 创建,使用 Stellar 作为主题。