Mar*_*cin 12 dependency-injection dagger-2
为了学习Dagger 2,我决定重写我的应用程序,但我仍然坚持为以下问题找到合适的解决方案.
出于这个例子的目的,让我们假设我们有一个名为的接口Mode:
public interface Mode {
Object1 obj1();
//some other methods providing objects for app
}
Run Code Online (Sandbox Code Playgroud)
和两个实现:
NormalMode和DemoMode.
模式存储在单例中,因此可以从应用程序中的任何位置访问.
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;
}
}
Run Code Online (Sandbox Code Playgroud)
在NormalMode切换到DemoMode在运行时(比方说,当背景几次用户clickcs)
public void backgroundClicked5Times(){
ModeManager.INSTANCE.mode(new DemoMode());
//from now on every object that uses Mode will get Demo implementations, great!
}
Run Code Online (Sandbox Code Playgroud)
所以首先我摆脱了单例并将模式定义为Dagger 2模块:
@Module
public class NormalModeModule {
@Provides
public Object1 provideObject1() {
return new NormalObject1();
}
}
@Module
public class DemoModeModule {
@Provides
public Object1 provideObject1() {
return new DemoObject1();
}
}
Run Code Online (Sandbox Code Playgroud)
现在在方法中backgroundClicked5Times而不是处理单例我想在DAG中替换NormalModeModule,DemoModeModule所以其他需要的类从现在开始Object1就会得到一个DemoObject1实现.
我怎么能在Dagger那样做?
提前致谢.
也许您可以考虑使用多重绑定?
@Module
public class NormalModeModule {
@Provides
@IntoMap
@StringKey("normal")
public Object1 provideObject1() {
return new NormalObject1();
}
}
@Module
public class DemoModeModule {
@Provides
@IntoMap
@StringKey("demo")
public Object1 provideObject1() {
return new DemoObject1();
}
}
Run Code Online (Sandbox Code Playgroud)
当使用模式时:
@Inject
Map<String, Mode> modes;
//or you perfer lazy initialization:
Map<String, Provider<Mode>> modes;
public void backgroundClicked5Times(){
ModeManager.INSTANCE.mode(modes.get("demo"));
//if you are using Provider:
ModeManager.INSTANCE.mode(modes.get("demo").get());
//from now on every object that uses Mode will get Demo implementations, great!
}
Run Code Online (Sandbox Code Playgroud)
在对 dagger 进行了一段时间的实验后,我想出了在我的用例中似乎运行良好的解决方案。
定义将保存有关模式的状态信息的类
public class Conf {
public Mode mode;
public Conf(Mode mode) {
this.mode = mode;
}
public enum Mode {
NORMAL, DEMO
}
}
Run Code Online (Sandbox Code Playgroud)Conf在模块中提供单例实例
@Module
public class ConfModule {
@Provides
@Singleton
Conf provideConf() {
return new Conf(Conf.Mode.NORMAL);
}
}
Run Code Online (Sandbox Code Playgroud)将模块添加到 AppComponent
@Singleton
@Component(modules = {AppModule.class, ConfModule.class})
public interface AppComponent {
//...
}
Run Code Online (Sandbox Code Playgroud)定义根据Mode提供不同对象的模块
@Module
public class Object1Module {
@Provides
Object1 provideObject1(Conf conf) {
if (conf.mode == Conf.Mode.NORMAL)
return new NormalObject1();
else
return new DemoObject1();
}
}
Run Code Online (Sandbox Code Playgroud)要在运行时切换模式,只需注入Conf对象并修改它:
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
}
}
Run Code Online (Sandbox Code Playgroud)