web-dev-qa-db-fra.com

Contexte dans MVVM sous Android

J'ai commencé à travailler sur l'architecture MVVM pour une application Android. J'ai un doute: est-il correct de passer le contexte pour voir le modèle? Sinon, comment mon modèle de vue peut-il accéder au contexte si nécessaire?.

Je fais les choses suivantes:

  1. Alimentez les données en utilisant un EditText.
  2. Envoyez ces données à View model.
  3. Voir le modèle envoyer ces données au référentiel
  4. Référentiel stockant ces données dans les préférences partagées du périphérique.

En tant que préférences partagées, le contexte est nécessaire pour instancier l'objet.

Je suis nouveau dans cette architecture, aucune orientation ne me serait utile, merci d'avance.

5
Lalit Kushwah

Je pense que l'utilisation de ApplicationContext est correcte. Vous pouvez étendre votre ViewModel à partir de AndroidViewModel et chaque fois que vous avez besoin d'une référence aux méthodes d'utilisation de contexte getApplication().

Mieux encore, si vous utilisez votre dague, vous n’avez absolument pas besoin de cela, vous n’injectez que votre ApplicationContext partout où vous en avez besoin. Cela peut être dans votre modèle de vue ou une classe utilitaire qui gère les préférences partagées, etc.

5
Reza

Il s’agit d’une longue discussion au sein de la communauté Android. Lorsque nous nous référons à MVC, il est évident que les modèles (objets de stockage de données) sont M, Controllers = C pour les classes d'activité (dans iOS, ils les appellent en fait UIViewControllers) et le V pour la vue dans Android est le fichier XML lui-même. Maintenant, certains discuteraient de la décomposition architecturale de ce qui représente quoi. Cependant, dépassons cela et discutons de MVVM.

MVVM existe depuis de nombreuses années. Il y a eu quelques tentatives dans le passé pour le transférer sur Android via des outils de liaison tiers, mais cela finit par être plus compliqué qu'il n'en vaut la peine.

Récemment, avec la publication de la liaison de données native, Android est enfin capable de procéder à une implémentation relativement propre de MVVM. Donc, il y a quelques options ici. Tu peux faire

M = Modèles (objets contenant des données)

V = Vues (le fichier XML lui-même représentant l'interface utilisateur)

VM = C'est ici que se déroulent les débats.

Certains disent que pour être un "vrai" ViewModel, il faut séparer véritablement la couche Présentation et que la classe Activity elle-même possède des rappels de cycle de vie, ce qui la rend indigne d'être appelée ViewModel.

D’autres (auto-inclus) font remarquer que pour gérer la plupart des actions déclenchées par le ViewModel, il faut être conscient de onActivityResult, onNewIntent, onBroadcastReceived, onPause ou d’autres manipulations de cycle de vie afin de gérer de manière appropriée l’expérience utilisateur. Donc, dans mon équipe, nous considérons l’activité comme ViewModel. Sinon, vous transmettez l'activité à un modèle de vue et vous les combinez de toute façon, créant ainsi un cauchemar de code géant.

Donc, si vous voulez mon avis, tenez-vous-en à traiter l'activité comme votre ViewModel. Transférez vos données dans le ViewModel comme n'importe quelle technologie de liaison telle que INotifyPropertyChanged dans WPF. Vous le faites à travers votre liaison.

Je fais deux choses pour y arriver. Une, j’ai une variable d’activité dans la présentation XML à injecter dans onCreate pour la configuration de liaison, qui donne à la liaison XML les droits de liaison directs sur toutes les propriétés observables dans le modèle de vue, autrement dit l’activité. Ensuite, j'injecte toutes les variables dont je dois me servir, par exemple, vous pouvez avoir un WeatherModel qui remplit une prévision qui vit dans l'activité que vous définissez également dans onCreate pour autoriser l'accès XML à ViewModel (ou activité). et c'est viewModel's Objects.

L’autre alternative est de créer un objet ViewModel et de l’injecter dans le code XML dans l’onCreate de votre activité, puis de continuer à rappeler l’activité au modèle de vue pour gérer les actions et les cycles de vie. Vous pouvez également gérer ce cauchemar haha, I J'ai fait tout un projet de cette façon et à la fin, j'ai tout refait pour éviter tout chevauchement des efforts de codage et des hideux échanges.

Goodluck et j'espère que ça aide.

4
Sam

Une très bonne question, et ce n'est pas aussi simple qu'il y paraît! Vous pouvez voir un exemple de l'équipe de Google ici .

Ils ont résolu le problème avec l'aide de l'usine. Là, on passe (bien sûr) le contexte de l’application (pas le contexte de l’activité!).

Un petit problème - et tant de code passe-partout!

Ma décision:

public class MainApplication extends Application {
public void onCreate() {
AppSharedPref sharedPref = AppSharedPref.getInstance(PreferenceManager.getDefaultSharedPreferences(this));
AppRepository.getInstance(sharedPref);

Le référentiel est unique (beaucoup de code est ignoré pour des raisons de brièveté):

public class AppRepository implements AppDataSource {
public static AppRepository getInstance(@NonNull AppSharedPref sharedPref) {
if (INSTANCE == null) {
   INSTANCE = new AppRepository(sharedPref);
}
return INSTANCE;
}

Dans ViewModel, appelez:

public class MyViewModel extends AndroidViewModel {

// constructor
public MyViewModel(@NonNull Application application) {
   repository = AppRepository.getInstance(.....);
}
2
tim4dev

Regardez dans Dagger 2!

C’est vrai, vous ne devriez définitivement pas passer Activity à votre xml ou ViewModel. Votre ViewModel ne sera pas meilleur que ces activités de 2000 lignes que nous essayons de quitter avec cette architecture. La solution que nous avons dans notre projet MVVM consiste à injecter SharedPreferences avec Dagger. Vous pouvez bien sûr utiliser ApplicationContext également, mais avez-vous besoin de plusieurs instances de SharedPreferences dans le projet?

Nous avons une classe utilitaire pour SharedPreferences et il est agréable de la garder comme un singleton et d’injecter où vous en avez besoin.

0
Rainmaker

Vous devez utiliser la classe AndroidViewModel ou conserver la référence au contexte de l'application dans votre implémentation ViewModel dans ce cas. La classe ViewModel a été conçue pour maintenir les données persistantes entre différentes instances de Activity tout au long de son cycle de vie et le stockage de références à l'un des contextes Activity n'a pas de sens.

0
Nikolay