web-dev-qa-db-fra.com

Observer LiveData à partir de ViewModel

J'ai une classe distincte dans laquelle je gère l'extraction de données (en particulier Firebase), auquel je renvoie habituellement des objets LiveData et que je mets à jour de manière asynchrone. Maintenant, je veux que les données renvoyées soient stockées dans un ViewModel, mais le problème est que pour obtenir ladite valeur, je dois observer l'objet LiveData renvoyé de ma classe d'extraction de données. La méthode observe nécessitait un objet LifecycleOwner en tant que premier paramètre, mais je ne l'ai évidemment pas dans mon ViewModel et je sais que je ne suis pas censé conserver de référence à l'activité/au fragment à l'intérieur du ViewModel. Que devrais-je faire?

51
Vuk Bibic

Dans cet article de blog du développeur Google Jose Alcérreca, il est recommandé d'utiliser une transformation dans ce cas (voir le paragraphe "LiveData dans les référentiels").

22
guglhupf

Dans ViewModel documentation

Toutefois, les objets ViewModel ne doivent jamais observer de modifications des observables sensibles au cycle de vie, tels que les objets LiveData.

Une autre solution consiste pour les données à implémenter RxJava plutôt que LiveData, elles n'auront donc pas l'avantage d'être sensibles au cycle de vie.

Dans l'exemple Google de todo-mvvm-live-kotlin , il utilise un rappel sans LiveData dans ViewModel.

Je suppose que si vous voulez vous conformer à l'idée d'être un cycle de vie, nous devons déplacer le code d'observation dans Activité/Fragment. Sinon, nous pouvons utiliser callback ou RxJava dans ViewModel.

Un autre compromis est d'implémenter MediatorLiveData (ou Transformations) et d'observer (mettez votre logique ici) dans ViewModel. Remarquez que l'observateur MediatorLiveData ne se déclenchera pas (comme pour les transformations) à moins que ce ne soit observé dans Activité/Fragment. Ce que nous faisons, c'est que nous mettons une observation vide dans Activité/Fragment, où le travail réel est réellement effectué dans ViewModel.

// ViewModel
fun start(id : Long) : LiveData<User>? {
    val liveData = MediatorLiveData<User>()
    liveData.addSource(dataSource.getById(id), Observer {
        if (it != null) {
            // put your logic here
        }
    })
}

// Activity/Fragment
viewModel.start(id)?.observe(this, Observer {
    // blank observe here
})

PS: j'ai lu ViewModels et LiveData: Patterns + AntiPatterns qui suggérait que Transformations. Je ne pense pas que cela fonctionne si on n'observe pas LiveData (ce qui nécessite probablement que cela soit fait dans Activité/Fragment).

17
Desmond Lua

Je pense que vous pouvez utiliser observeForever, qui ne nécessite pas l'interface propriétaire du cycle de vie et vous permet d'observer les résultats du modèle de vue.

1
siddharth