2015-11-20 1 views
4

Comment pouvez-vous remplacer les dépendances dans différentes portées de Dagger 2? Exemple:Comment remplacer les dépendances dans Scopes in Dagger 2

J'ai deux composants dans mon application: ApplicationComponent et ActivityComponent. ApplicationComponent est le composant de base et ActivityComponent est un composant sectoriel dans lequel je souhaite effectuer le remplacement.

Pour cet exemple, je créé ces modèles:

public class Parrot { 

    private final HelloPrinter helloPrinter; 

    public Parrot(HelloPrinter helloPrinter) { 
     this.helloPrinter = helloPrinter; 
    } 

    public void sayHello(){ 
     helloPrinter.print(); 
    } 
} 


public interface HelloPrinter { 
    void print(); 
} 


public class AppHelloPrinter implements HelloPrinter{ 

    @Override 
    public void print() { 
     System.out.println("Hello Application"); 
    } 
} 

public class ActivityHelloPrinter implements HelloPrinter { 
    @Override 
    public void print() { 
     System.out.println("Hello Activity"); 
    } 
} 

Et le code:

ApplicationComponent applicationComponent = DaggerApplicationComponent.builder().build(); 
applicationComponent.provideParrot().sayHello(); 
activityComponent = DaggerActivityComponent.builder() 
         .applicationComponent(applicationComponent).build(); 
activityComponent.provideParrot().sayHello(); 

Ma sortie désirée est:

Hello Application 
Hello Activity 

Je fait les modules:

ApplicationModule:

@Singleton 
@Component(modules = ApplicationModule.class) 
public interface ApplicationComponent { 

    Parrot provideParrot(); 
} 

@Module 
public class ApplicationModule { 

    @Provides 
    @Singleton 
    HelloPrinter providePrinter(){ 
     return new AppHelloPrinter(); 
    } 

    @Provides 
    Parrot provideParrot(HelloPrinter helloPrinter) { 
     return new Parrot(helloPrinter); 
    } 

} 

ActivityModule: tente de remplacer le HelloPrinter

@PerActivity 
@Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class) 
public interface ActivityComponent { 

    Parrot provideParrot(); 

} 

@Module 
@PerActivity 
public class ActivityModule { 

    @Provides 
    @PerActivity 
    HelloPrinter provideHelloPrinter() { 
     return new ActivityHelloPrinter(); 
    }  
} 

Mais avec cette config la sortie est:

Hello Application 
Hello Application 

Qu'est-ce que je fais mal? Merci

+0

Je pense qu'il n'est pas possible de remplacer le module dans Dagger2. Si cela vous convient, vous pouvez essayer de les marquer comme @Named ("Activité") et @Named ("Application") –

Répondre

2

La réponse courte est ... vous ne pouvez pas faire cela.

Avec poignard, tout est fait au moment de la compilation.

  1. Vous avez un composant d'application, qui sait comment construire un HelloPrinter et un Parrot.
    Vous devez ensuite afficher le Parrot pour tous les composants à utiliser. Vous avez votre composant d'activité, qui sait aussi comment construire un HelloPrinter!

Alors, que se passe-t-il? Gardez à l'esprit le graphe d'objets.

Les composants savent ce qu'ils peuvent créer et dépendent d'autres composants, exposant eux-mêmes les objets connus.

applicationComponent.provideParrot().sayHello(); 

Celui-ci est facile. Vous créez le composant, vous voulez un perroquet et il est construit en utilisant l'imprimante connue.

activityComponent.provideParrot().sayHello(); 

Ce qui se passe ici, est (fondamentalement) le même. Vous dites que vous voulez un perroquet. Votre composant d'activité ne sait pas en faire un, il sait juste comment faire une imprimante!
Mais attendez. Il a une dépendance sur un composant d'application, ce qui expose facilement une usine Parrot.

La fabrique de composants d'application est appelée et le perroquet est instancié. Depuis le module d'application sait comment construire une imprimante, il utilise celui à portée de main.

... maintenant ce que

Alors ... vous pouvez fournir Perroquets dans votre composante d'activité, ils utiliseraient alors une autre imprimante!

Gradle: error: Parrot is bound multiple times

Ici, nous aurions 2 Perroquets dans notre graphe d'objets, car il n'y a pas de "écrasement" qui se passe. Cela ne fonctionnera pas, et ne devrait pas.

Conclusion

Il n'y a aucun moyen de dérogation méthodes. Dès que vous déclarez une seconde Parrot ou HelloPrinter, la compilation échouera.

La seule possibilité d'obtenir une fonctionnalité similaire serait d'utiliser les annotations @Named() sur l'imprimante à utiliser et/ou de tirer la création entière de perroquet dans le module d'activité.

Et s'il vous plaît corrigez-moi s'il me manque quelque chose, mais je ne vois même pas un moyen de garder la même signature avec des annotations nommées.