安卓系统中的 MVVM(模型视图视图模型)架构模式
原文:https://www . geesforgeks . org/mvvm-model-view-view model-architecture-pattern-in-Android/
开发人员总是更喜欢项目的干净和结构化的代码。根据设计模式组织代码有助于软件的维护。通过了解安卓应用的所有关键逻辑部分,添加和删除应用功能变得更加容易。此外,设计模式还确保所有代码都包含在单元测试中,而不受其他类的干扰。Model—View—View Model(MVVM)是业界公认的软件架构模式克服了 MVP 和 MVC 设计模式的所有缺点。MVVM 建议将数据呈现逻辑(视图或用户界面)与应用程序的核心业务逻辑部分分开。
MVVM 的独立代码层为:
- 模型:这个层负责数据源的抽象。模型和视图模型一起工作来获取和保存数据。
- 视图:该层的目的是告知 ViewModel 用户的动作。该层观察视图模型,不包含任何类型的应用程序逻辑。
- 视图模型:它公开了那些与视图相关的数据流。此外,它充当模型和视图之间的链接。
MVVM 模式与 MVP(模型-视图-演示者)设计模式有一些相似之处,因为演示者角色由视图模型扮演。然而,MVVM 通过以下方式解决了 MVP 模式的缺点:
- 视图模型不包含对视图的任何类型的引用。
- 视图和视图模型之间存在多对一的关系。
- 没有更新视图的触发方法。
如何在项目中实施 MVVM
在安卓项目中实现 MVVM 设计模式有两种方式:
- 使用谷歌发布的数据绑定库
- 使用任何像 RxJava 这样的工具进行数据绑定。
数据绑定:
谷歌为安卓发布了数据绑定库,允许开发人员将 XML 布局中的用户界面组件与应用程序的数据存储库绑定。这有助于最小化与视图绑定的核心应用程序逻辑的代码。此外,双向数据绑定用于将对象绑定到 XML 布局,以便对象和布局都可以相互发送数据。这一点可以通过本教程的示例来可视化。
双向数据绑定的语法是@ = {变量}
MVVM 建筑模式范例
这是一个单一活动用户登录安卓应用程序的例子,展示了 MVVM 架构模式在项目中的实现。应用程序将要求用户输入电子邮件标识和密码。基于接收到的输入,视图模型通知视图显示什么作为敬酒信息 。视图模型不会引用视图。
要在 android 应用程序中启用数据绑定,需要在应用程序的 build.gradle(build.gradle (:app))文件中添加以下代码:
启用数据绑定:
安卓{
数据绑定{
使能=真
}
}
添加生命周期依赖关系:
实现‘Android . arch . life cycle:extensions:1 . 1 . 1’
下面是带有 MVVM 模式的用户登录安卓应用程序的完整分步实现。
逐步实施
注意:在 Android Studio 版本上执行以下步骤
第一步:创建新项目
- 单击文件,然后单击新建= >新建项目。
- 选择空活动
- 选择语言为 Java/Kotlin
- 根据您的需要选择最小的软件开发工具包。
第二步:修改 String.xml 文件
活动中使用的所有字符串都列在该文件中。
可扩展标记语言
<resources>
<string name="app_name">GfG | MVVM Architecture</string>
<string name="heading">MVVM Architecture Pattern</string>
<string name="email_hint">Enter your Email ID</string>
<string name="password_hint">Enter your password</string>
<string name="button_text">Login</string>
</resources>
步骤 3:创建模型类
创建一个名为模型的新类,该类将保存用户输入的电子邮件标识和密码。下面是实现适当的模型类的代码。
Java 语言(一种计算机语言,尤用于创建网站)
import androidx.annotation.Nullable;
public class Model {
@Nullable
String email,password;
// constructor to initialize
// the variables
public Model(String email, String password){
this.email = email;
this.password = password;
}
// getter and setter methods
// for email variable
@Nullable
public String getEmail() {
return email;
}
public void setEmail(@Nullable String email) {
this.email = email;
}
// getter and setter methods
// for password variable
@Nullable
public String getPassword() {
return password;
}
public void setPassword(@Nullable String password) {
this.password = password;
}
}
第 4 步:使用 activity_main.xml 文件
打开 activity_main.xml 文件,添加 2 EditText 获取电子邮件和密码的输入。还需要一个登录按钮来验证用户的输入并显示适当的吐司消息。以下是设计适当活动布局的代码。
注意:为了数据绑定库的正常运行,需要在顶部设置布局标签。在这种情况下,XML 的约束布局标签将不起作用。
可扩展标记语言
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/tools">
<!-- binding object of ViewModel to the XML layout -->
<data>
<variable
name="viewModel"
type="com.example.mvvmarchitecture.AppViewModel" />
</data>
<!-- Provided Linear layout for the activity components -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="8dp"
android:background="#168BC34A"
android:orientation="vertical">
<!-- TextView for the heading of the activity -->
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/heading"
android:textAlignment="center"
android:textColor="@android:color/holo_green_dark"
android:textSize="36sp"
android:textStyle="bold" />
<!-- EditText field for the Email -->
<EditText
android:id="@+id/inEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="60dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="20dp"
android:hint="@string/email_hint"
android:inputType="textEmailAddress"
android:padding="8dp"
android:text="@={viewModel.userEmail}" />
<!-- EditText field for the password -->
<EditText
android:id="@+id/inPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:hint="@string/password_hint"
android:inputType="textPassword"
android:padding="8dp"
android:text="@={viewModel.userPassword}" />
<!-- Login Button of the activity -->
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="60dp"
android:layout_marginEnd="20dp"
android:background="#4CAF50"
android:fontFamily="@font/roboto"
android:onClick="@{()-> viewModel.onButtonClicked()}"
android:text="@string/button_text"
android:textColor="@android:color/background_light"
android:textSize="30sp"
android:textStyle="bold"
bind:toastMessage="@{viewModel.toastMessage}" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="135dp"
app:srcCompat="@drawable/banner" />
</LinearLayout>
</layout>
第 5 步:创建视图模型类
这个类将包含应用程序布局中需要调用的所有方法。视图模型类将扩展基本可观察的,因为它将数据转换成流,并在吐司消息属性发生变化时通知视图。
Java 语言(一种计算机语言,尤用于创建网站)
import android.text.TextUtils;
import android.util.Patterns;
import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
public class AppViewModel extends BaseObservable {
// creating object of Model class
private Model model;
// string variables for
// toast messages
private String successMessage = "Login successful";
private String errorMessage = "Email or Password is not valid";
@Bindable
// string variable for
// toast message
private String toastMessage = null;
// getter and setter methods
// for toast message
public String getToastMessage() {
return toastMessage;
}
private void setToastMessage(String toastMessage) {
this.toastMessage = toastMessage;
notifyPropertyChanged(BR.toastMessage);
}
// getter and setter methods
// for email variable
@Bindable
public String getUserEmail() {
return model.getEmail();
}
public void setUserEmail(String email) {
model.setEmail(email);
notifyPropertyChanged(BR.userEmail);
}
// getter and setter methods
// for password variable
@Bindable
public String getUserPassword() {
return model.getPassword();
}
public void setUserPassword(String password) {
model.setPassword(password);
notifyPropertyChanged(BR.userPassword);
}
// constructor of ViewModel class
public AppViewModel() {
// instantiating object of
// model class
model = new Model("","");
}
// actions to be performed
// when user clicks
// the LOGIN button
public void onButtonClicked() {
if (isValid())
setToastMessage(successMessage);
else
setToastMessage(errorMessage);
}
// method to keep a check
// that variable fields must
// not be kept empty by user
public boolean isValid() {
return !TextUtils.isEmpty(getUserEmail()) && Patterns.EMAIL_ADDRESS.matcher(getUserEmail()).matches()
&& getUserPassword().length() > 5;
}
}
步骤 6:在主活动文件中定义视图的功能
视图类负责更新应用程序的用户界面。根据视图模型提供的 toast 消息中的变化,绑定适配器将触发视图层。Toast 消息的设置者将通知观察者(视图)数据的变化。之后,视图将采取适当的操作。
Java 语言(一种计算机语言,尤用于创建网站)
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.BindingAdapter;
import androidx.databinding.DataBindingUtil;
import com.example.mvvmarchitecture.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ViewModel updates the Model
// after observing changes in the View
// model will also update the view
// via the ViewModel
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
activityMainBinding.setViewModel(new AppViewModel());
activityMainBinding.executePendingBindings();
}
// any change in toastMessage attribute
// defined on the Button with bind prefix
// invokes this method
@BindingAdapter({"toastMessage"})
public static void runMe( View view, String message) {
if (message != null)
Toast.makeText(view.getContext(), message, Toast.LENGTH_SHORT).show();
}
}
输出
[https://media.geeksforgeeks.org/wp-content/uploads/20201028015557/MVVMOutputRecording.mp4](https://media.geeksforgeeks.org/wp-content/uploads/20201028015557/MVVMOutputRecording.mp4)MVVM 建筑的优势
- 增强代码的可重用性。
- 所有模块都是独立的,这提高了每一层的可测试性。
- 使项目文件易于维护和更改。
MVVM 建筑的缺点
- 这种设计模式对于小项目来说并不理想。
- 如果数据绑定逻辑太复杂,应用程序调试会稍微困难一些。
版权属于:月萌API www.moonapi.com,转载请注明出处