J'ai une application utilisant la classe Androids ViewModel et le composant de navigation pour naviguer entre les fragments. Comment gérer la navigation depuis le ViewModel? J'utilise RxJava et je pensais que les Fragments écoutent les événements de navigation, puis déclenchent la navigation de cette façon. Quelle est la manière normale de gérer cela? J'utilise également Dagger pour l'injection de dépendance si cela aide.
Si vous utilisiez MVP, P appellerait simplement la méthode sur V qui déclenche la navigation.
L'approche équivalente dans MVVM serait d'avoir un observable/écouteur/rappel dédié, si cela est fait avec RxJava, il pourrait être piloté par un PublishSubject
. Cela satisfait l'exigence ponctuelle. Si, au lieu de cela, vous devez répondre aux événements qui peuvent être émis avant de vous abonner, vous pouvez utiliser un BehaviorSubject<Optional<T>>
Et le créer avec createDefault(absent<T>())
, le déclencher avec onNext(Optional.of(navigationObject))
puis laissez le VM savoir quand la navigation se produit, puis le VM peut l'effacer avec onNext(absent())
Alternativement, si vous souhaitez le transformer en un état de type redux/mvi englobant, vous pourriez avoir une classe d'état avec tout l'état, y compris une propriété qui indique à la vue de naviguer quelque part, lors de la réception/de l'action sur cette vue dire à VM qu'il l'a fait et la fonction VM définirait l'état au même que actuel mais sans navigation. ex. (dans Kotlin) state = state.copy(navigateToX = false)
Par LiveData with SnackBar, Navigation, and other events blog post :
Certaines données ne doivent être consommées qu'une seule fois, comme un message Snackbar, un événement de navigation ou un déclencheur de dialogue.
Au lieu d'essayer de résoudre ce problème avec des bibliothèques ou des extensions des composants d'architecture, cela devrait être considéré comme un problème de conception. Nous vous recommandons de traiter vos événements comme faisant partie de votre état.
Ils détaillent l'utilisation d'une classe SingleLiveEvent qui garantit que chaque événement de navigation n'est reçu qu'une seule fois par un observateur (c'est-à-dire votre fragment qui a accès à votre NavController
).
L'autre alternative consiste à utiliser un modèle "Event wrapper" où l'événement doit être explicitement marqué comme géré.