web-dev-qa-db-fra.com

Lier un service à une activité ou à un fragment?

Je travaille sur une application de lecteur de musique. J'ai une activité principale qui comporte plusieurs fragments, chacun affichant des chansons sur l'album de l'appareil, par artiste, etc.
J'ai un service de musique qui gère toutes les lectures et autres.
Ce qui me rend confus, c’est la liaison de ce service avec divers fragments que j’ai.
À l’heure actuelle, je lie l’activité principale et chaque fragment individuellement avec le service et son fonctionnement est excellent. Mais je me demandais si c'était vraiment la meilleure pratique? Existe-t-il un moyen de lier l’activité principale au service, puis de l’utiliser dans ses fragments enfants?
Il me manque peut-être un concept très élémentaire d'activité, de fragments ou de services. Si quelqu'un me guide s'il vous plaît à cet égard.
Je suppose que c’est plus une question conceptuelle que tout code n’est pas nécessaire. Mais si cela est nécessaire, merci de me le faire savoir. 

MODIFIER :
Ma question est la suivante: quel serait le meilleur moyen de lier un service à une activité avec plusieurs fragments enfants (dont chacun utiliserait le service)?

16
Anjani

Je pense que l’architecture cleanear consiste à lier directement le fragment. En ce qui concerne le problème décrit dans la réponse de Rarw, vous pouvez également vous connecter au service à partir de votre activité et de vos fragments. De cette façon, vous êtes sûr que le service sera disponible jusqu'à ce que l'activité ne soit pas détruite. 

Je peux voir deux avantages principaux de la connexion à partir du fragment:

  1. La connexion au service étant asynchrone, vous n'êtes donc jamais vraiment sûr que le service que vous obtenez de l'activité n'est pas nul. Cela vous mènera au moins à certaines vérifications de pointeur nul et à un mécanisme permettant d'actualiser le fragment à la fois lorsqu'il est créé et lorsque le service se connecte (vous êtes donc sûr d'afficher les données, peu importe laquelle des deux se produit en premier).
  2. Vous ne dépendez pas de l'activité particulière laissée par vos fragments. Pour obtenir le service de l'activité, je pense que vous effectuez un transfert vers la classe spécifique à l'activité. Vous pouvez créer une interface comme BoundActivity avec une méthode telle que getBoundService pour obtenir le service, mais je pense que c'est une surcharge compte tenu de l'avantage du point 1. Et si vous disposiez de plusieurs services.

METTRE À JOUR

Voici un projet très simple montrant cela . https://github.com/ena1106/FragmentBoundServiceExample

16
Ena

La seule méthode que j’ai trouvée fiable consiste à utiliser un chargeur dans Fragment:

  1. créer une Loader dans le fragment
  2. utilisez la context de la Loader (définie sur activity dans initLoader à l'appel de onCreate du fragment)
  3. lier le service dans onStartLoading, en utilisant une ServiceConnection qui appelle forceLoad() dès que le service est lié
  4. éventuellement enregistrer des rappels dans onStartLoading/onStopLoading
  5. dissocier le service dans onStopLoading
0
junique

vous pouvez utiliser le modèle de bus d'événements avec cette bibliothèque, modèle de publication/abonnement eventbus. https://github.com/greenrobot/EventBus consultez le site du projet pour plus d'informations.

vous pouvez envoyer des événements de/à un service à actif ou à des fragments

0
ingyesid

SI vous devez obtenir des données de votre service sur votre fragment au début de son cycle de vie, l'activité onServiceConnected on ne peut pas encore être appelée, principalement lorsque vous faites pivoter votre appareil, et vous obtiendrez un NPE. Je pense que c'est une bonne idée de laisser fragment établir ses propres connexions puisque le service est démarré avec startService () et non avec bindService ().

0
Informatheus

Vous pouvez accéder à votre activité à partir d'un fragment par getActivity()

0

Je lie le service dans l'activité Mon hôte et passe l'objet d'Ibinder par Bundle qui est défini dans les arguments.

et mon code peut aimer ça:

private ServiceConnection mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        //put service in bundle
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
};
0
fantianwen