web-dev-qa-db-fra.com

Dague @Reusable scope vs @Singleton

Depuis le Guide de l'utilisateur :

Parfois, vous voulez limiter le nombre de fois où une classe construite par @ Inject est instanciée ou une méthode @Provides est appelée, mais vous n'avez pas besoin de garantir que la même instance exacte est utilisée pendant la durée de vie d'un composant ou sous-composant particulier.

Pourquoi devrais-je utiliser cela au lieu de @Singleton?

36
philo

Utilisez @Singleton si vous comptez sur le comportement et les garanties singleton. Utilisez @Reusable si un objet ne serait un @Singleton que pour des raisons de performances.


Les liaisons @ réutilisables ont beaucoup plus en commun avec les liaisons non étendues que les liaisons @Singleton: vous dites à Dagger que vous feriez bien de créer un objet flambant neuf, mais s'il y a déjà un objet pratique créé, alors Dagger peut utilisez celui-là. En revanche, les objets @Singleton garantissent que vous toujours recevrez l'instance même, ce qui peut coûter beaucoup plus cher imposer.

En général, Dagger et DI préfèrent les objets non délimités: la création d'un nouvel objet est un excellent moyen de conserver un état étroitement confiné et permet de récupérer les ordures des objets dès que l'objet dépendant le peut. Dagger montre une partie de cette préférence intégrée: dans Dagger, les objets non étendus peuvent être mélangés à n'importe quel composant ou module, que le composant soit annoté ou non. Ce type de liaison non étendue est également utile pour les objets sans état comme les classes utilitaires injectables (moquables) et les implémentations de stratégie , commande , et d'autres polymorphes comportementauxdesign patterns : Les objets doivent être liés globalement et injectés pour les tests/remplacements, mais les instances ne gardent aucun état et sont de courte durée ou jetables.

Cependant, dans Android et autres environnements soumis à des contraintes de performances et de mémoire, il va à l'encontre des recommandations de performances de créer un grand nombre d'objets temporaires , car la création d'instances et la récupération de place sont deux processus plus coûteux que sur les machines virtuelles de bureau. Cela conduit à la solution pragmatique de marquer un objet @Singleton, non pas parce qu'il est important de toujours obtenir la même instance, mais simplement de conserver les instances. Cela fonctionne, mais est sémantiquement faible, et a également des implications de mémoire et de vitesse: votre objet de modèle d'utilisation ou de stratégie de courte durée maintenant doit exister tant que votre application existe, et doit être accessible via un verrouillage à double vérification, sinon vous risquez violant la garantie "une seule instance" @Singleton (ce qui n'est pas nécessaire ici). Cela peut être une source d'utilisation accrue de la mémoire et de surcharge de synchronisation.

Le compromis se trouve dans les liaisons @ réutilisables, qui ont des propriétés de conservation d'instance comme @Singleton mais sont à l'exception de la règle @Component correspondant à la portée tout comme les liaisons non étendues - ce qui vous donne plus de flexibilité sur l'endroit où vous les installez . (Voir tests .) Ils ont une durée de vie aussi longtemps que le composant le plus externe qui les utilise directement, et utiliseront opportunément une instance d'un ancêtre pour les conserver davantage, mais sans double vérification verrouillage pour économiser sur les coûts de création. Enfin et surtout, ils sont un signal pour vous et les futurs développeurs sur la manière dont la classe est destinée à être utilisée.

En bref, @Singleton fonctionnerait, mais @Reusable a des avantages de performances distincts si le point entier est la performance au lieu du cycle de vie de l'objet.


Question de suivi de saiedmomen : "Juste pour être clair à 100%, des choses comme okhttpclient, retrofit et gson doivent être déclarées @ Réutilisable. Non ?? "

Oui, en général, je pense qu'il serait bon de déclarer utilitaires et bibliothèques sans état comme @Reusable. Cependant, s'ils gardent secrètement un état, comme la gestion des limites de connexion ou le traitement par lots sur tous les consommateurs, vous souhaiterez peut-être les faire @Singleton, et s'ils sont très rarement utilisés à partir d'un composant à longue durée de vie il pourrait être judicieux de les rendre sans portée afin qu'ils puissent être récupérés. Il est vraiment difficile de faire ici une déclaration générale qui fonctionne pour tous les cas et bibliothèques: vous devrez décider en fonction de la fonctionnalité de la bibliothèque, du poids de la mémoire, du coût d'instanciation et de la durée de vie attendue des objets impliqués.

OkHttpClient en particulier gère ses propres pools de connexions et de threads par instance , comme Wyko le souligne dans les commentaires; cela en ferait un bon candidat pour @Singleton plus de @Reusable. Merci Wyko!

73
Jeff Bowman