104 votes

Comment et où utiliser Transformations.switchMap ?

Dans la récente bibliothèque Android Architecture Components publiée par Google, nous avons deux fonctions statiques dans la section Transformations classe. Alors que le map est directe et facilement compréhensible, mais j'ai du mal à comprendre correctement la fonction de gestion de l'information. switchMap fonction.

La documentation officielle de switchMap se trouve à l'adresse suivante aquí .

Quelqu'un peut-il expliquer comment et où utiliser la fonction switchMap avec un exemple pratique ?

2 votes

Voir aussi Quelle est la différence entre les méthodes map() et switchMap() ? . Il ne s'agit peut-être pas d'un duplicata à 100%, mais il contient des explications très utiles.

164voto

Damia Fuentes Points 1194

En el map() función

LiveData userLiveData = ...;
LiveData userName = Transformations.map(userLiveData, user -> {
     return user.firstName + " " + user.lastName; // Returns String
});

chaque fois que la valeur de userLiveData changements, userName sera également mis à jour. Remarquez que nous retournons un String .

En el switchMap() fonction :

MutableLiveData userIdLiveData = ...;
LiveData userLiveData = Transformations.switchMap(userIdLiveData, id ->
    repository.getUserById(id)); // Returns LiveData

void setUserId(String userId) {
     this.userIdLiveData.setValue(userId);
}

chaque fois que la valeur de userIdLiveData changements, repository.getUserById(id) sera appelée, tout comme la fonction map. Mais repository.getUserById(id) renvoie un LiveData . Ainsi, chaque fois que la valeur de la LiveData retourné par repository.getUserById(id) change, la valeur de userLiveData changera aussi. Ainsi, la valeur de userLiveData dépendra des changements de userIdLiveData et les changements de la valeur de repository.getUserById(id) .

Exemple pratique de switchMap() Imaginons que vous ayez un profil d'utilisateur avec un bouton "suivre" et un bouton "profil suivant" qui définit une autre information de profil. Le bouton next profile appellera setUserId() avec un autre id, donc userLiveData va changer et l'interface utilisateur va changer. Le bouton "Suivre" appellera le DAO pour ajouter un follower de plus à cet utilisateur, ainsi l'utilisateur aura 301 followers au lieu de 300. userLiveData aura cette mise à jour qui vient du référentiel, qui vient de la DAO.

1 votes

Donc, en gros, c'est un moyen d'écouter quelques sources de changement de vos données en même temps. Si l'identifiant change, vos userLiveData changent, et si les valeurs de l'utilisateur réel changent, vos userLiveData changent aussi. N'est-ce pas ? (Vous pourriez probablement empiler quelques transformations pour connecter encore plus de LiveData ensemble, bien que vous devriez probablement utiliser MediatorLiveData aussi).

4 votes

Quelques informations sur l'architecture des transformations, elles sont plus utilisées au niveau du ViewModel car elles permettent de transformer les données du type provenant du DAO en un type qui doit être affiché à l'IU, donc, imaginez que vous avez une fonctionnalité d'ajout au panier, vous allez ajouter des éléments à un panier , disons que ce panier est un hashmap qui correspond à chaque id de produit avec un élément dans une liste, ce hashmap vient de la DAO, mais au lieu de passer ce hashmap à l'interface utilisateur, nous utilisons une transformation pour convertir ce hashmap en une liste conviviale à afficher dans l'interface utilisateur, maintenant HashMap<String,Cart> sera transformé en List<Cart>.

0 votes

Est-ce un bon exemple ? Cela semble impliquer que vous faites un appel à la base de données dans la section switchMap callback, alors que la doc indique : "La fonction donnée func sera exécuté sur le thread principal. "

34voto

nag prakash Points 145

J'ajoute mes 2 centimes à la réponse de @DamiaFuentes.

MutableLiveData userIdLiveData = ...;
LiveData userLiveData = Transformations.switchMap(userIdLiveData, id ->
repository.getUserById(id)); // Returns LiveData

void setUserId(String userId) {
     this.userIdLiveData.setValue(userId);
}

La méthode Transformations.switchMap ne sera appelée que si vous avez au moins un observateur pour userLiveData.

5 votes

Merci beaucoup @Prakash, j'avais du mal à trouver pourquoi mon switchMap n'écoutait pas les changements dans le trigger.

11 votes

Avant, j'étais un homme simple. Quand je n'ai pas pu comprendre ce concept, j'ai fait quelque chose de mon cru. Dans ce cas, j'ai créé une classe entière avec une source de données personnalisée, des constructeurs, etc. jusqu'à ce que je me heurte à un blocage mental. Votre réponse m'a fait redevenir un homme simple. J'ai supprimé cette classe.

0 votes

Repository.getUserById(id) ; Comment gérer le cas où switchmap() est appelé sur le getUserById(), la condition mutabledata != null

30voto

Sonu Sanjeev Points 373

Pour ceux qui veulent plus d'explications sur la fonction @DamiaFuentes switchmap(), voici un exemple :

 MutableLiveData userIdLiveData = ...;
 LiveData userLiveData = Transformations.switchMap(userIdLiveData, id ->
     repository.getUserById(id));

 void setUserId(String userId) {
      this.userIdLiveData.setValue(userId);
 }

Dans un scénario où le référentiel contient User(1, "Jane") et User(2, "John"), lorsque la valeur userIdLiveData est définie sur "1", le switchMap appelle getUser(1), qui renvoie une LiveData contenant la valeur User(1, "Jane"). Donc maintenant, le userLiveData émettra User(1, "Jane"). Lorsque l'utilisateur du référentiel sera mis à jour en User(1, "Sarah"), le userLiveData sera automatiquement notifié et émettra User(1, "Sarah").

Lorsque la méthode setUserId est appelée avec userId = "2", la valeur de la userIdLiveData change et déclenche automatiquement une requête pour obtenir l'utilisateur avec l'id "2" du référentiel. Ainsi, le userLiveData émet User(2, "John"). La LiveData renvoyée par repository.getUserById(1) est supprimée comme source.

À partir de cet exemple, nous pouvons comprendre que le userIdLiveData est le déclencheur et que le LiveData renvoyé par le repository.getUserById est le LiveData "backing".

Pour plus de références, consultez le site : https://developer.Android.com/reference/Android/arch/lifecycle/Transformations

1 votes

Arch est déprécié : Utilisez ceci developer.Android.com/reference/androidx/lifecycle/

0 votes

Comment définir la requête par défaut pour la chaîne de recherche dans switchmap ?

5voto

Arda Kazancı Points 73

La fonction passée à switchMap renvoie des LiveData. Utilisez-la lorsque votre référentiel renvoie lui-même des LiveData.

4voto

Jim Ovejera Points 114

Un autre point à prendre en compte pour choisir entre switchMap ou map vous devez vous rappeler que map enroule toujours la valeur retournée autour de LiveData par exemple

fun getUser(id: Int): User 
...
val userId = MutableLiveData(1)
val user = userId.map { // LiveData<User>
   repository.getUser(it)
}

Vous pouvez envisager d'utiliser map si repository.getUser(it) renvoie un simple User au lieu de LiveData le type d'utilisateur devient donc LiveData<User> .

Si repository.getUser(it) renvoie un LiveData<User> alors il est préférable d'utiliser switchMap

fun getUser(id: Int): LiveData<User>
...
val userId = MutableLiveData(1)
val user = userId.switchMap { // LiveData<User>
   repository.getUser(it)
}

El user Le type serait LiveData<User>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X