Inside the module, if I need to provide a different implementation of the interface based on the variable known at the time the module was built, I can put the logic inside the @Provides method for this type of interface. For instance:
@Module public class FooModule { private final State state; public FooModule(State state) { this.state = state; } @Provides FooInterface provideFooImplementation() { switch(state) { case STATE_1: return new FooImpl1(); case STATE_2: return new FooImpl2(); ... case STATE_10: return new FooImpl10(); } } }
However, these implementations can be created with a dagger. I would say, "Hey, based on X, I want you to create this class for me."
I have considered several options.
Change the rendering method to use all possible implementations:
@Provides FooInterface provideFooImplementation(FooImpl1 impl1, FooImpl2 imp2, ..., FooImpl10 impl10) { switch(state) { case STATE_1: return impl1; case STATE_2: return impl2; ... case STATE_10: return impl10; } }
This allows the dagger to create them and satisfy all their dependencies, but it is not a good idea if each of the implementations is relatively large or expensive to create.
Modify the rendering method to collectively take all the dependencies for different implementations.
@Provides FooInterface provideFooImplementation(Context context, Repo repo, HttpClient httpClient, ...) { switch(state) { case STATE_1: return new FooImpl1(context); case STATE_2: return new FooImpl2(repo, httpClient); ... case STATE_10: return new FooImpl10(context, repo); } }
This is slightly better than option 1 in that the Dagger should not create an instance of each individual implementation, but it still needs to create instances of all the dependencies, even if they cannot be used in all cases. I will also return to creating objects myself, even if they can be created with a dagger.
Create one module for each implementation and create the corresponding module. So something like:
@Module public FooImpl1Module { @Provides FooInterface provideFooImplementation(Context context) { return new FooImpl1(context); } }
This will be fine, but now I have problems defining a component that depends on the module.
What is the best way to solve this problem?
One suggestion was to try option 1 with parameters wrapped in Lazy. Then I end up calling .get () on one. I will try it when I can, and publish the results
source share