Dans ce tutoriel, nous discuterons et mettrons en œuvre le Modèle Architectural MVVM Android dans notre Application Android. Nous avons précédemment discuté du Modèle MVP Android.
Pourquoi avons-nous besoin de ces modèles ? Ajouter tout dans une seule Activité ou Fragment pourrait entraîner des problèmes lors des tests et du refactoring du code. Par conséquent, l’utilisation de la séparation du code et de l’architecture propre est recommandée.
Android MVVM
MVVM signifie Modèle, Vue, ViewModel.
- Modèle: Il contient les données de l’application. Il ne peut pas communiquer directement avec la Vue. En général, il est recommandé d’exposer les données au ViewModel via des Observables.
- Vue: Elle représente l’interface utilisateur de l’application dépourvue de toute logique d’application. Elle observe le ViewModel.
- ViewModel: Il fait le lien entre le Modèle et la Vue. Il est responsable de la transformation des données du Modèle. Il fournit des flux de données à la Vue. Il utilise également des hooks ou des rappels pour mettre à jour la Vue. Il demandera les données au Modèle.
Le flux suivant illustre le modèle MVVM de base. En quoi cela diffère-t-il du MVP ?
- Le ViewModel remplace le Présentateur dans la couche intermédiaire.
- Le Présentateur détient des références vers la Vue. Le ViewModel non.
- Le Présentateur met à jour la Vue en utilisant la manière classique (en déclenchant des méthodes).
- Le ViewModel envoie des flux de données.
- Le Présentateur et la Vue sont en relation un à un.
- La Vue et le ViewModel sont en relation un à plusieurs.
- Le ViewModel ne sait pas que la Vue écoute ses modifications.
Il existe deux façons d’implémenter MVVM sur Android :
- La liaison de données
- RXJava
Dans ce tutoriel, nous n’utiliserons que la liaison de données. La bibliothèque de liaison de données a été introduite par Google afin de lier directement les données dans la mise en page xml. Pour plus d’informations sur la liaison de données, consultez ce tutoriel. Nous créerons un exemple d’application de page de connexion simple qui demande des saisies utilisateur. Nous verrons comment le ViewModel notifie la Vue quand afficher un message Toast sans conserver de référence de la Vue.
Comment est-il possible de notifier une classe sans en avoir de référence ? Cela peut être fait de trois manières différentes :
- En utilisant la liaison de données bidirectionnelle
- En utilisant LiveData
- En utilisant RxJava
La liaison de données bidirectionnelle
La liaison de données bidirectionnelle est une technique de liaison de vos objets à vos mises en page XML de telle sorte que l’objet et la mise en page puissent tous deux s’envoyer des données. Dans notre cas, le ViewModel peut envoyer des données à la mise en page et également observer les changements. Pour cela, nous avons besoin d’un BindingAdapter
et d’un attribut personnalisé défini dans le XML. L’adaptateur de liaison écouterait les changements dans la propriété de l’attribut. Nous en apprendrons davantage sur la liaison de données bidirectionnelle à travers notre exemple ci-dessous.
Structure de projet d’exemple Android MVVM
Ajout de la bibliothèque de liaison de données
Ajoutez le code suivant au fichier build.gradle de votre application :
android {
dataBinding {
enabled = true
}
}
Cela active la liaison de données dans votre application.
Ajout des dépendances
Ajoutez les dépendances suivantes dans votre fichier build.gradle
:
implementation 'android.arch.lifecycle:extensions:1.1.0'
Modèle
Le modèle contiendrait l’e-mail et le mot de passe de l’utilisateur. La classe User.java suivante le fait :
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;
}
}
La liaison de données bidirectionnelle nous permet de lier des objets dans les mises en page XML de manière à ce que l’objet puisse envoyer des données à la mise en page, et vice versa. La syntaxe pour la liaison de données bidirectionnelle est @={variable}
Mise en page
Le code pour activity_main.xml est donné ci-dessous :
<?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>
La liaison de données nécessite de définir la balise de mise en page en haut. Ici, notre ViewModel lie les données à la Vue. ()-> viewModel.onLoginClicked()
invoque le lambda du gestionnaire de clic de bouton défini dans notre ViewModel. L’EditText met à jour les valeurs dans le modèle (via ViewModel). bind:toastMessage="@{viewModel.toastMessage}"
est un attribut personnalisé que nous avons créé pour la liaison de données bidirectionnelle. En fonction des changements dans toastMessage dans le ViewModel, l’BindingAdapter serait déclenché dans la Vue.
ViewModel
Le code pour LoginViewModel.java est donné ci-dessous :
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;
}
}
Les méthodes appelées dans la mise en page sont implémentées dans le code ci-dessus avec la même signature. Si le pendant XML de la méthode n’existe pas, nous devons changer l’attribut en app:
. La classe ci-dessus peut également étendre ViewModel. Mais nous avons besoin de BaseObservable car elle convertit les données en flux et notifie lorsque la propriété toastMessage
est modifiée. Nous devons définir le getter et le setter pour l’attribut personnalisé toastMessage défini dans le XML. À l’intérieur du setter, nous notifions l’observateur (qui sera la Vue dans notre application) que les données ont changé. La Vue (notre activité) peut définir l’action appropriée.
La classe BR est générée automatiquement à partir de la liaison de données lorsque vous reconstruisez le projet
Le code de la classe MainActivity.java
est donné ci-dessous:
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();
}
}
Grâce à la liaison de données, la classe ActivityMainBinding
est générée automatiquement à partir de la mise en page. La méthode @BindingAdapter
est déclenchée chaque fois que l’attribut toastMessage défini sur le bouton est modifié. Elle doit utiliser le même attribut que celui défini dans le XML et dans le ViewModel. Ainsi, dans l’application ci-dessus, le ViewModel met à jour le Modèle en écoutant les changements dans la Vue. De plus, le Modèle peut mettre à jour la vue via le ViewModel en utilisant notifyPropertyChanged
. Le résultat de l’application ci-dessus en action est donné ci-dessous: Cela marque la fin de ce tutoriel sur Android MVVM utilisant la liaison de données. Vous pouvez télécharger le projet via le lien donné ci-dessous.
Source:
https://www.digitalocean.com/community/tutorials/android-mvvm-design-pattern