web-dev-qa-db-fra.com

BoundService + LiveData + ViewModel Meilleures pratiques dans la nouvelle architecture recommandée par Android

Je me suis beaucoup battu pour savoir où placer les services Android dans le nouveau Android recommandé Architecture . J'ai proposé de nombreuses solutions possibles, mais je ne peux pas me décider sur laquelle est la meilleure approche.

J'ai fait beaucoup de recherches et je n'ai trouvé aucun guide ni tutoriel utile. Le seul indice que j'ai trouvé sur l'emplacement du service dans l'architecture de mon application est celui-ci, de @JoseAlcerreca Medium post

Idéalement, ViewModels ne devrait rien savoir d’Android. Cela améliore la testabilité, la sécurité des fuites et la modularité. En règle générale, assurez-vous qu'il n'y a pas d'Android. * Dans votre ViewModels (avec des exceptions comme Android.Arch. *). La même chose s'applique aux présentateurs.

Par conséquent, je devrais placer mes services Android au sommet de la hiérarchie de mes composants d'architecture, au même niveau que mes activités et mes fragments. En effet, les services Android font partie du cadre Android et ViewModels ne devrait donc pas les connaître.

Maintenant, je vais expliquer brièvement mon scénario, mais uniquement pour clarifier le panorama, pas parce que je veux une réponse pour ce scénario spécifique.

  • J'ai une application Android qui a une MainActivity avec de nombreux fragments, tous liés dans un BottomNavBar.
  • J'ai un service Bluetooth lié à myActivity et à l'un de ses fragments (parce que je veux que le service ait le même cycle de vie que l'Activty, mais je souhaite également interagir avec ce dernier directement à partir de mon fragment).
  • Le fragment interagit avec le BluetoothService pour obtenir deux types d’informations:
    • Informations sur l'état de la connexion Bluetooth. N'a pas besoin d'être persistant.
    • Les données provenant du périphérique Bluetooth (il s'agit d'une balance, donc du poids et de la composition corporelle dans ce cas). Doit être persisté.

Voici les 3 différentes architectures auxquelles je peux penser:

LiveData dans AndroidService LiveData inside Android Service Arch

  • Les données LiveData avec l’état de la connexion et les mesures de poids Provenant du périphérique Bluetooth se trouvent dans le BluetoothService.
  • Le fragment peut déclencher des opérations dans le BluetoothService (scanDevices par exemple)
  • Le fragment observe les données LiveData à propos de l'état de la connexion .__ et adapte l'interface utilisateur en conséquence (par exemple, activez un bouton si l'état Est connecté).
  • Le fragment observe les données LiveData des nouvelles mesures de poids. Si une nouvelle mesure de poids provient de BluetoothDevice, le fragment demande alors à son propre ViewModel de sauvegarder les nouvelles données. Cela se fait via une classe Repository.

ViewModel partagé entre fragment et AndroidService Shared ViewModel Arch

  • Le fragment peut déclencher des opérations dans le BluetoothService (scanDevices par exemple)
  • BluetoothService met à jour les données LiveData liées à Bluetooth dans le ViewModel partagé.
  • Le fragment observe les données LiveData dans son propre ViewModel.

Service ViewModel Service ViewMOdel Arch

  • Le fragment peut déclencher des opérations dans le BluetoothService (scanDevices par exemple)
  • BluetoothService met à jour les données LiveData liées à Bluetooth dans son propre ViewModel.
  • Le fragment observe les données LiveData dans son propre ViewModel et dans le BluetoothService ViewModel.

Je suis presque certain que je devrais les placer au-dessus de l'architecture et les traiter comme une activité/un fragment, car BoundServices fait partie du cadre Android, ils sont gérés par le système d'exploitation Android et sont liés à d'autres activités et fragments. Dans ce cas, je ne sais pas quel est le meilleur moyen d'interagir avec LiveData, ViewModels et Activities/Fragments.

Certains pourraient penser qu'ils devraient être considérés comme une source de données (car dans mon cas, les données sont mesurées à l'aide de Bluetooth), mais je ne pense pas que ce soit une bonne idée, à cause de tout ce que j'ai dit dans le paragraphe précédent. et spécialement à cause de ce qui est écrit ici

Évitez de désigner les points d’entrée de votre application, tels que les activités, services et les récepteurs de diffusion, en tant que sources de données. Au lieu de cela, ils ne doivent se coordonner qu'avec d'autres composants pour récupérer le sous-ensemble de données pertinentes pour ce point d’entrée. Chaque application composant est plutôt de courte durée, en fonction de l'interaction de l'utilisateur avec leur appareil et la santé globale actuelle du système.

Donc, finalement, ma question est la suivante: 

Où devrions-nous placer nos services Android (Bound) et quelle est leur relation avec les autres composants architecturaux? Est-ce que l'une ou l'autre de ces alternatives est une bonne approche?

13
dglozano

Un objet d'interface est un moyen d'éviter le contact direct avec un service Android tout en restant utilisable. Cela fait partie du "I" pour Interface Segregation dans l'acronyme, SOLID. Voici un petit exemple:

public interface MyFriendlyInterface {
    public boolean cleanMethodToAchieveBusinessFunctionality();
    public boolean anotherCleanMethod();
}

public class MyInterfaceObject implements MyFriendlyInterface {
    public boolean cleanMethodToAchieveBusinessFunctionality() {
        BluetoothObject obj = Android.Bluetooth.nastySubroutine();
        Android.Bluetooth.nastySubroutineTwo(obj);
    }

    public boolean anotherCleanMethod() {
        Android.Bluetooth.anotherMethodYourPresentersAndViewModelsShouldntSee();
    }
}

public class MyViewModel {
    private MyFriendlyInterface _myInterfaceObject;

    public MyViewModel() {
        _myInterfaceObject = new MyInterfaceObject();
        _myInterfaceObject.cleanMethodToAchieveBusinessFunctionality();
    }
}

Compte tenu du paradigme ci-dessus, vous êtes libre de placer vos services dans un package ne contenant pas de code POJO, qui se trouve en dehors de celui-ci. Il n’existe pas d’emplacement "adéquat" pour mettre vos services - mais il existe certainement des endroits FAUX pour les placer (par exemple, où va votre code POJO). 

0
Grant Park