In order to learn Dagger 2 i decided to rewrite my application but I'm stuck with finding the proper solution for the following problem.
For the purpose of this example let's assume we have an interface called Mode
:
public interface Mode {
Object1 obj1();
//some other methods providing objects for app
}
and two implementations:
NormalMode
and DemoMode
.
Mode is stored in singleton so it could be accessed from anywhere within application.
public enum ModeManager {
INSTANCE,;
private Mode mode;
public Mode mode() {
if (mode == null)
mode = new NormalMode();
return mode;
}
public void mode(Mode mode) { //to switch modules at runtime
this.mode = mode;
}
}
The NormalMode
is switched to DemoMode
at runtime (let's say, when user clickcs on background couple of times)
public void backgroundClicked5Times(){
ModeManager.INSTANCE.mode(new DemoMode());
//from now on every object that uses Mode will get Demo implementations, great!
}
So first I got rid of the singleton and defined Modes as Dagger 2 modules:
@Module
public class NormalModeModule {
@Provides
public Object1 provideObject1() {
return new NormalObject1();
}
}
@Module
public class DemoModeModule {
@Provides
public Object1 provideObject1() {
return new DemoObject1();
}
}
Now in the method backgroundClicked5Times
instead of dealing with singleton I would like to replace NormalModeModule
with DemoModeModule
in DAG so the other classes that need Object1
would get a DemoObject1
implementation from now on.
How can I do that in Dagger?
Thanks in advance.
Inject values at runtime with UI in Dagger2:pureMathModule("Book Name") . build() . inject(this); The difference between DaggerComponent create() and in build() is - create() works when no runtime argument is passed into the constructor, else we use build() method.
In order to use dependency injection with the help of dagger 2 libraries, we need to add it's dependency. Go to Gradle Scripts > build. gradle(Module: app) and add the following dependencies. After adding these dependencies you need to click on Sync Now.
The @Inject annotation println("Heater is hot !!!") Each class has an empty constructor with the @Inject annotation. This allows instances of these classes to be constructed by Dagger. The @Singleton annotation means that Dagger will create and maintain a single instance of the annotated class.
Having experimented with dagger for a while I came up with solution that seems to be working well in my use case.
Define class that will hold state information about mode
public class Conf {
public Mode mode;
public Conf(Mode mode) {
this.mode = mode;
}
public enum Mode {
NORMAL, DEMO
}
}
Provide singleton instance of Conf
in Module
@Module
public class ConfModule {
@Provides
@Singleton
Conf provideConf() {
return new Conf(Conf.Mode.NORMAL);
}
}
Add module to AppComponent
@Singleton
@Component(modules = {AppModule.class, ConfModule.class})
public interface AppComponent {
//...
}
Define modules that provide different objects based on Mode
@Module
public class Object1Module {
@Provides
Object1 provideObject1(Conf conf) {
if (conf.mode == Conf.Mode.NORMAL)
return new NormalObject1();
else
return new DemoObject1();
}
}
To switch mode at runtime simply inject Conf
object and modify it:
public class MyActivity extends Activity {
@Inject Conf conf;
//...
public void backgroundClicked5Times(){
conf.mode = Conf.Mode.DEMO;
//if you have dagger objects in this class that depend on Mode
//execute inject() once more to refresh them
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With