web-dev-qa-db-fra.com

Passer des données d'un modèle de vue à un autre Android MVVM

J'ai une question liée au design pour vous les gars.

J'ai donc suivi Guide to App Architecture par Google pour créer mon application en utilisant Kotlin, MVVM et la liaison de données. J'utilise des composants Jetpack (navigation, liveata, etc.) comme prescrit par Google.

Le problème est que plusieurs fois pendant le développement, j'ai besoin de transférer des données d'un fragment à un autre. Plus tôt, j'avais l'habitude de créer une instance du fragment et d'ajouter les données complexes, puis de passer au fragment, comme ceci:

class Frag1: Fragment(){

    ...
    fun openFrag2(){
        val frg2 = frag2.newInstance(complexDataObj)
        childFragmentManager.addFragment(frg2,TAG)
    }
}

class Frag2: Fragment(){
    var cd: ComplexDataClass = null
    companion object{
    fun newInstance(complexData: ComplexDataClass): Fragment{
        val frag = ActivityFragment()
        frag.cd = complexData
        return frag
    }
    ....
}

Avec navigation le passage de données entre les destinations est supposé être comme this ou utiliser Shared View Model qui est également mentionné dans la même documentation. >>

En général, vous devriez fortement préférer ne transmettre que la quantité minimale de données entre les destinations. Par exemple, vous devez passer une clé pour récupérer un objet plutôt que de passer l'objet lui-même, car l'espace total pour tous les états enregistrés est limité sur Android. Si vous devez transmettre de grandes quantités de données , envisagez d'utiliser un ViewModel comme décrit dans Partager des données entre fragments.

Cela fonctionne.

Ce qui me pose problème, c'est que l'une des principales raisons d'utiliser une architecture est la séparation des préoccupations; Afin que nous puissions écrire du code propre et maintenable. Cette utilisation de sharedviewmodel va à l'encontre de cet objectif (selon ma compréhension) car cela conduit à de grandes classes ViewModel.

J'essaierai d'expliquer le problème avec un scénario assez courant.

J'ai un fragment avec une liste de données. Chaque élément de la liste correspond à un utilisateur. Lorsque nous tapotons sur un élément, il devrait se déplacer vers un écran de détails utilisateur, si nous tapons sur le bouton de modification, nous devons passer à l'écran de modification où les détails peuvent être modifiés.

             View User Frag
             ____                 ____________
            |    |               |            |
 List Frag  |    |               |            |
 ______     |____|               |            |
|______| /
|______|/                        |            |
|______|\                        |            | Huge Shared ViewModel class
|______| \
            Edit User Frag       |            |
            _____
           |     |               |            |
           |     |
           |_____|               |____________|

Donc, dans cette situation, le ViewModel sera partagé entre ces 3 fragments car les données utilisateur doivent être envoyées de la classe de liste à la vue et modifiez les fragments, et le ViewModel partagé aura la logique métier des trois fragments.

Donc, cela ne me semble pas juste, car le ViewModel sera trop complexe à gérer dans de nombreux cas en tant que partage comme celui-ci:

model = activity?.run {
        ViewModelProviders.of(this)[SharedViewModel::class.Java]
    } ?: throw Exception("Invalid Activity")

donnera la même instance du viewmodel.

J'ai besoin de savoir si ma compréhension de ce modèle de vue partagée est erronée, si c'est le cas, veuillez me corriger. Si ma compréhension est bonne, veuillez me faire savoir comment gérer le modèle de vue plus efficacement dans de tels cas.

6
hushed_voice

Vous pouvez avoir plusieurs ViewModel dans un Fragment, donc il n'est pas nécessaire de garder un énorme ViewModel partagé avec toute la logique des 3 plus petits.

Vous pouvez créer un ViewModel partagé supplémentaire qui ne se soucie que des données communes réelles et garder vos 3 ViewModels spécifiques aux fragments séparés séparés.

sharedModel = activity?.run {
        ViewModelProviders.of(this)[SharedViewModel::class.Java]
    } ?: throw Exception("Invalid Activity")
localViewModel = ViewModelProviders.of(this).get(LocalViewModel::class.Java)
1
Mircea Nistor