android mvvm_Android MVVM设计模式

android mvvm

In this tutorial, we’ll be discussing and implementing the Android MVVM Architectural Pattern in our Android Application. We’ve previously discussed the Android MVP Pattern.

在本教程中,我们将在Android应用程序中讨论和实现Android MVVM架构模式。 我们之前已经讨论了Android MVP模式

Why do we need these patterns? 为什么我们需要这些模式?
Adding everything in a Single Activity or Fragment would lead to problems in testing and refactoring the code. Hence, the use of separation of code and clean architecture is recommended.
在“单个活动”或“片段”中添加所有内容会导致测试和重构代码时出现问题。 因此,建议使用代码分离和干净的体系结构。

Android MVVM (Android MVVM)

MVVM stands for Model, View, ViewModel.

MVVM代表ModelViewViewModel

  • Model: This holds the data of the application. It cannot directly talk to the View. Generally, it’s recommended to expose the data to the ViewModel through Observables.

    型号 :它保存应用程序的数据。 它不能直接与视图对话。 通常,建议通过Observables将数据公开给ViewModel。
  • View: It represents the UI of the application devoid of any Application Logic. It observes the ViewModel.

    视图 :它表示没有任何应用程序逻辑的应用程序的UI。 它观察ViewModel。
  • ViewModel: It acts as a link between the Model and the View. It’s responsible for transforming the data from the Model. It provides data streams to the View. It also uses hooks or callbacks to update the View. It’ll ask for the data from the Model.

    ViewModel :它充当模型和视图之间的链接。 它负责转换模型中的数据。 它向视图提供数据流。 它还使用挂钩或回调来更新视图。 它将要求从模型中获取数据。

The following flow illustrates the core MVVM Pattern.

以下流程说明了核心MVVM模式。

How does this differ from MVP?

这与MVP有何不同?

  • ViewModel replaces the Presenter in the Middle Layer.

    ViewModel替换中间层中的Presenter。
  • The Presenter holds references to the View. The ViewModel doesn’t.

    演示者持有对视图的引用。 ViewModel没有。
  • The Presenter updates the View using the classical way (triggering methods).

    演示者使用经典方式(触发方法)更新视图。
  • The ViewModel sends data streams.

    ViewModel发送数据流。
  • The Presenter and View are in a 1 to 1 relationship.

    演示者和视图处于一对一关系。
  • The View and the ViewModel are in a 1 to many relationship.

    View和ViewModel是一对多的关系。
  • The ViewModel does not know that the View is listening to it.

    ViewModel不知道View正在监听它。

There are two ways to implement MVVM in Android:

有两种在Android中实现MVVM的方法:

  • Data Binding

    数据绑定
  • RXJava

    接收Java

In this tutorial, we’ll be using Data Binding only.
Data Binding Library was introduced by Google in order to bind data directly in the xml layout. For more info on Data Binding, refer this tutorial.

在本教程中,我们将仅使用数据绑定。
Google引入了数据绑定库,以便直接在xml布局中绑定数据。 有关数据绑定的更多信息,请参阅教程。

We’ll be creating a simple Login Page Example Application that asks for user inputs. We’ll see how the ViewModel notifies the View when to show a Toast Message without keeping a reference of the View.

我们将创建一个简单的登录页面示例应用程序,要求用户输入。 我们将看到ViewModel如何在不显示View引用的情况下何时显示Toast消息时通知View。

How is it possible to notify some class without having a reference of it?

在没有参考的情况下如何通知某个类?

It can be done in three different ways:

可以通过三种不同的方式完成此操作:

  • Using Two Way Data Binding

    使用双向数据绑定
  • Using Live Data

    使用实时数据
  • Using RxJava

    使用RxJava

双向数据绑定 (Two Way Data Binding)

Two-way Data Binding is a technique of binding your objects to your XML layouts such that the Object and the layout can both send data to each other.

双向数据绑定是一种将对象绑定到XML布局的技术,这样对象和布局都可以相互发送数据。

In our case, the ViewModel can send data to the layout and also observe changes.

在我们的例子中,ViewModel可以将数据发送到布局并观察更改。

For this, we need a BindingAdapter and custom attribute defined in the XML.

为此,我们需要在XML中定义的BindingAdapter和自定义属性。

The Binding Adapter would listen to changes in the attribute property.

绑定适配器将侦听attribute属性中的更改。

We’ll learn more about Two-way Data Binding through our example below.

通过下面的示例,我们将学习有关双向数据绑定的更多信息。

Android MVVM示例项目结构 (Android MVVM Example Project Structure)

添加数据绑定库 (Adding the Data Binding Library)

Add the following code to your app’s build.gradle file:

将以下代码添加到您应用的build.gradle文件中:

android {

    dataBinding {
        enabled = true
    }
}

This enables Data Binding in your Application.

这将在您的应用程序中启用数据绑定。

添加依赖项 (Adding the Dependencies)

Add the following dependencies in your build.gradle file :

build.gradle文件中添加以下依赖build.gradle

implementation 'android.arch.lifecycle:extensions:1.1.0'

模型 (Model)

The Model would hold the user’s email and password. The following User.java class does it:

该模型将保存用户的电子邮件和密码。 以下User.java类可以实现此目的:

package com.journaldev.androidmvvmbasics.model;


public class User {
    private String email;
    private String password;

    public User(String email, String password) {
        this.email = email;
        this.password = password;
    }

    public void setEmail(String email) {
        this.email = email;
    }


    public String getEmail() {
        return email;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    public String getPassword() {
        return password;
    }


}

Two-way Data Binding allows us to bind objects in the XML layouts such that the object can send data to the layout, and vice versa.

双向数据绑定允许我们在XML布局中绑定对象,以便该对象可以将数据发送到布局,反之亦然。

The Syntax for two way data binding is @={variable}

双向数据绑定的语法为@={variable}

布局 (Layout)

The code for the activity_main.xml is given below:

下面给出了activity_main.xml的代码:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:bind="https://schemas.android.com/tools">

    <data>

        <variable
            name="viewModel"
            type="com.journaldev.androidmvvmbasics.viewmodels.LoginViewModel" />
    </data>


    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="8dp"
            android:orientation="vertical">

            <EditText
                android:id="@+id/inEmail"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Email"
                android:inputType="textEmailAddress"
                android:padding="8dp"
                android:text="@={viewModel.userEmail}" />


            <EditText
                android:id="@+id/inPassword"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Password"
                android:inputType="textPassword"
                android:padding="8dp"
                android:text="@={viewModel.userPassword}" />


            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:onClick="@{()-> viewModel.onLoginClicked()}"
                android:text="LOGIN"
                bind:toastMessage="@{viewModel.toastMessage}" />


        </LinearLayout>

    </ScrollView>

</layout>

Data Binding requires us to set the layout tag at the top. Here our ViewModel binds the data to the View.
()-> viewModel.onLoginClicked() invokes the Button click listener lambda defined in our ViewModel.
The EditText updates the values in the Model (via View Model).

数据绑定要求我们在顶部设置布局标签。 在这里,我们的ViewModel将数据绑定到View。
()-> viewModel.onLoginClicked()调用在我们的ViewModel中定义的Button点击监听器lambda。
EditText更新模型中的值(通过View Model)。

bind:toastMessage="@{viewModel.toastMessage}" is a custom attribute we’ve created for two-way data binding.
Based on changes in the toastMessage in the ViewModel the BindingAdapter would get triggered in the View.

bind:toastMessage="@{viewModel.toastMessage}"是我们为双向数据绑定创建的自定义属性。
根据ViewModel中toastMessage中的更改,将在View中触发BindingAdapter。

视图模型 (ViewModel)

The code for the LoginViewModel.java is given below:

下面给出了LoginViewModel.java的代码:

package com.journaldev.androidmvvmbasics.viewmodels;

import android.databinding.BaseObservable;
import android.databinding.Bindable;
import android.text.TextUtils;
import android.util.Patterns;

import com.android.databinding.library.baseAdapters.BR;
import com.journaldev.androidmvvmbasics.model.User;

public class LoginViewModel extends BaseObservable {
    private User user;


    private String successMessage = "Login was successful";
    private String errorMessage = "Email or Password not valid";

    @Bindable
    private String toastMessage = null;


    public String getToastMessage() {
        return toastMessage;
    }


    private void setToastMessage(String toastMessage) {

        this.toastMessage = toastMessage;
        notifyPropertyChanged(BR.toastMessage);
    }


    public void setUserEmail(String email) {
        user.setEmail(email);
        notifyPropertyChanged(BR.userEmail);
    }

    @Bindable
    public String getUserEmail() {
        return user.getEmail();
    }

    @Bindable
    public String getUserPassword() {
        return user.getPassword();
    }

    public void setUserPassword(String password) {
        user.setPassword(password);
        notifyPropertyChanged(BR.userPassword);
    }

    public LoginViewModel() {
        user = new User("","");
    }

    public void onLoginClicked() {
        if (isInputDataValid())
            setToastMessage(successMessage);
        else
            setToastMessage(errorMessage);
    }

    public boolean isInputDataValid() {
        return !TextUtils.isEmpty(getUserEmail()) && Patterns.EMAIL_ADDRESS.matcher(getUserEmail()).matches() && getUserPassword().length() > 5;
    }
}

The methods were called in the layout are implemented in the above code with the same signature.
If the XML counterpart of the method doesn’t exist, we need to change the attribute to app:.

在布局中调用的方法在上述代码中以相同的签名实现。
如果该方法的XML对应项不存在,则需要将属性更改为app:

The above class can also extend ViewModel. But we need BaseObservable since it converts the data into streams and notifies when the toastMessage property is changed.

上面的类还可以扩展ViewModel。 但是我们需要BaseObservable,因为它将数据转换为流并在toastMessage属性更改时通知。

We need to define the getter and setter for the toastMessage custom attribute defined in the XML.
Inside the setter, we notify the observer (which will be the View in our application) that the data has changed.
The View(Our activity) can define the appropriate action.

我们需要为XML中定义的toastMessage自定义属性定义getter和setter。
在设置器内部,我们通知观察者(在我们的应用程序中为View)数据已更改。
View(我们的活动)可以定义适当的操作。

BR class is auto-generated from data binding when you rebuild the project
重建项目时,BR类是根据数据绑定自动生成的

The code for the MainActivity.java class is given below:

MainActivity.java类的代码如下:

package com.journaldev.androidmvvmbasics.views;


import android.databinding.BindingAdapter;
import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;


import com.journaldev.androidmvvmbasics.R;
import com.journaldev.androidmvvmbasics.databinding.ActivityMainBinding;
import com.journaldev.androidmvvmbasics.viewmodels.LoginViewModel;


public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        activityMainBinding.setViewModel(new LoginViewModel());
        activityMainBinding.executePendingBindings();

    }

    @BindingAdapter({"toastMessage"})
    public static void runMe(View view, String message) {
        if (message != null)
            Toast.makeText(view.getContext(), message, Toast.LENGTH_SHORT).show();
    }
}

Thanks to DataBinding, the ActivityMainBinding class is auto-generated from the layout.
The @BindingAdapter method gets triggered whenever toastMessage attribute defined on the Button is changed.
It must use the same attribute as defined in the XML and in the ViewModel.

多亏了DataBinding, ActivityMainBinding类是从布局自动生成的。
每当在Button上定义的toastMessage属性更改时,都会触发@BindingAdapter方法。
它必须使用与XML和ViewModel中定义的属性相同的属性。

So in the above application, the ViewModel updates the Model by listening to the changes in the View.
Also, the Model can update the view via the ViewModel using the notifyPropertyChanged

因此,在上述应用程序中,ViewModel通过侦听View中的更改来更新Model。
此外,模型可以使用notifyPropertyChanged通过ViewModel更新视图

The output of the above application in action is given below:

android mvvm data binding demo

上面应用程序的输出如下:

This brings an end to this tutorial on Android MVVM Using DataBinding. You can download the project from the link given below.

这结束了有关使用数据绑定的Android MVVM上的本教程。 您可以从下面给出的链接下载项目。

翻译自: https://www.journaldev.com/20292/android-mvvm-design-pattern

android mvvm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值