Dagger 2: how to change the provided dependencies at runtime

To learn Dagger 2, I decided to rewrite my application, but I was stuck in finding the right solution for the next problem.

For this example, suppose we have an interface named Mode :

 public interface Mode { Object1 obj1(); //some other methods providing objects for app } 

and two implementations: NormalMode and DemoMode .

The mode is stored in singleton mode, so it can be accessed from anywhere in the 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; } } 

NormalMode switches to DemoMode at runtime (say when the user clicks several times in the background)

 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 the 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 backgroundClicked5Times method, instead of dealing with singleton, I would like to replace NormalModeModule with DemoModeModule in the DAG so that other classes that need Object1 get the implementation of DemoObject1 from now on.

How can I do this in a dagger?

Thanks in advance.

+7
dependency-injection dagger-2
source share
1 answer

After experimenting with the dagger for a while, I came up with a solution that seems to work well in my use case.

  • Define a class that will store mode status information

     public class Conf { public Mode mode; public Conf(Mode mode) { this.mode = mode; } public enum Mode { NORMAL, DEMO } } 
  • Provide a single instance of Conf in the 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 the mode at runtime, simply insert the Conf object and change 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 } } 
+1
source share

All Articles