How do I tell Dagger 2 which implementation to instantiate based on X?

后端 未结 3 663
既然无缘
既然无缘 2021-01-18 04:31

Inside a module, if I need to provide a different implementation of an interface based on a variable known at module construction time I can put the logic inside the @Provid

相关标签:
3条回答
  • 2021-01-18 05:03

    Have you tried something like this?

    public class hectic extends Iam {
    
        String tokenizer heccas = new string tokenizer();
    }
    
    0 讨论(0)
  • 2021-01-18 05:10

    A possible solution would be using @Named("foo") annotation in conjunction with favoring component provision method over manual injection, which would however mean that your state would be independent from the module itself, and you'd be the one to make your choice

    @Component(modules={FooModule.class})
    public interface AppComponent {
        @Named("STATE_1")
        FooInterface fooImpl1();
        @Named("STATE_2")
        FooInterface fooImpl2();
        ...
        @Named("STATE_10")
        FooInterface fooImpl10();
    }
    
    @Module
    public FooImpl1Module {
        @Provides
        @Named("STATE_1")
        FooInterface provideFooImpl1(Context context) {
            return new FooImpl1(context);
        }
    
        @Provides
        @Named("STATE_2")
        FooInterface provideFooImpl2(Context context) {
            return new FooImpl2(context);
        }
    
        ...
    
        @Provides
        @Named("STATE_10")
        FooInterface provideFooImpl10(Context context) {
            return new FooImpl10(context);
        }
    }
    

    Then you can call

    FooInterface fooInterface = component.fooImpl1();
    
    0 讨论(0)
  • 2021-01-18 05:27

    Rather than Lazy<T>, do option 1 with Provider<T>. Lazy<T> is just a Provider<T> that memoizes locally (with the necessary double-checked locking), but because you know you'll only call one Provider exactly once, you can just inject the Provider instead and skip the synchronization overhead.

    @Provides
    FooInterface provideFooImplementation(
            Provider<FooImpl1> impl1,
            Provider<FooImpl2> impl2,
            ...,
            Provider<FooImpl10> impl10) {
        switch(state) {
            case STATE_1:
                return impl1.get();
            case STATE_2:
                return impl2.get();
            ...
            case STATE_10:
                return impl10.get();
        }
    }
    

    Option 2 will work, but you'll effectively skip the dependency wiring that Dagger could easily do for you, and Option 3 won't work as stated because your @Component annotation needs your list of modules to be a compile-time constant for your Dagger code generation to work.

    (A variant of Option 3 could work if your binding were to a constant or a zero-dependency class of one form or another, because then you could pass in an arbitrary subclass of your Module into your Component builder. However, Dagger can only analyze the bindings in the superclass module, and you'd have trouble if your @Provides method implementations take different parameters as yours would, so the switch is the best and clearest alternative I can think of.)

    0 讨论(0)
提交回复
热议问题