web-dev-qa-db-fra.com

Dague 2 - Quel est le but d'une classe d'annotation @Singleton

Depuis le poignard 2 Documentation J'ai remarqué que vous pouvez avoir une classe annotée @Singleton. Quel est le but de marquer une classe en tant que @Singleton comme j'ai essayé de le faire dans mon code mais un objet singleton n'est PAS produit. Je ne comprends pas à quoi sert de marquer ma classe avec cette annotation. 

Dans la documentation, veuillez vous concentrer sur la déclaration suivante:

L'annotation @Singleton sur une classe injectable sert également de Documentation. Cela rappelle aux mainteneurs potentiels que cette classe peut être partagé par plusieurs threads. *

@Singleton
class CoffeeMaker {
  ...
}

UPDATE: Après avoir examiné la réponse de froger_mcs, je vois que dans Dagger 2, vous pouvez fournir des injections soit par un module OR, soit par une injection de constructeur. Donc, la classe suivante, bien que pas dans un module, peut être injectée:

@Singleton
public class MyClass {

    @Inject
    public MyClass() {

    }
}

Dans cette version, le constructeur est injecté pour nous et dans une activité Android, vous feriez simplement ce qui suit et il vous sera fourni:

@Inject
MyClass myClass;
//then in onCreate actually inject(this) from your graph of course.
26
j2emanue

@Singleton (et toute autre annotation de portée) transforme votre classe en une instance unique dans votre graphe de dépendances (cela signifie que cette instance sera "singleton" tant que l'objet Component existe). 

En bref, chaque fois que vous injectez une classe annotée @Singleton (avec une annotation @Inject), il s'agira de la même instance tant que vous l'injecterez à partir du même composant.

Pour en savoir plus, je fais référence à mon article sur le fonctionnement de @Singleton et d'autres annotations Scopes dans Dagger 2: http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/

36
froger_mcs

@Singleton ne crée pas vraiment un Singleton, c'est juste un Scope, il est conseillé de ne pas utiliser @Singleton car c'est trompeur, cela donne l'impression que nous sommes en train d'obtenir un Singleton, mais nous ne le sommes pas.

Supposons que vous annotiez votre dépendance à la base de données avec @Singleton et que vous associez une Component, supposons maintenant que vous initialisez cette Component dans ActivitiesA et B, vous aurez différentes instances de votre base de données dans vos deux Activities .

Comment surmontez-vous cela?

Initialisez votre Component une fois dans votre classe Application et accédez-y de manière statique dans des emplacements tels que Activities ou Fragments. Désormais, cela pourrait vite devenir incontrôlable si vous avez plus de 20 Component's, car vous ne pouvez pas les initialiser dans votre classe Application ralentissez également le temps de lancement de votre application.

La meilleure solution selon moi est de créer une vraie Singleton, soit une double vérification ou une autre variante, et l’utiliser statiquement comme getInstance() et l’utiliser sous @Provides dans votre module.

Je sais que cela me brise aussi le cœur, mais comprenez bien que @Singleton n’est pas vraiment un Singleton, c’est un Scope.

19
Arif Nadeem

Eh bien, vous pouvez créer manuellement une annotation, ce qui aidera à créer un singleton object.

@Scope
@Retention(RetentionPolicy.CLASS)
public @interface MyApplicationScope {
}

Lorsque l'annotation @MyApplicationScope est ajoutée avec l'annotation @Provides, elle permet au poignard de créer un objet une seule fois et d'utiliser le même objet à l'avenir. N'oubliez pas d'ajouter cette annotation à l'interface du composant, sinon vous obtiendrez l'erreur liée à la portée lors de la compilation.

Si vous utilisez l'annotation @Singleton, vous pouvez créer les nouveaux objets à chaque fois que vous créerez votre composant avec .build().

1
Levon Petrosyan