gpt4 book ai didi

java - Dagger 2 的可交换模块

转载 作者:行者123 更新时间:2023-11-29 04:50:22 26 4
gpt4 key购买 nike

所以我有一些运行算法的代码,比如使用 AlgoRunner 类。现在这个 AlgoRunner 类可以通过多种方式实现,以使用 Algo 类运行不同的算法。我想使用 Dagger 2 为“管理器”类提供 AlgoRunner 类的不同实现,该类将输入传递给 AlgoRunner 以及它管理的其他组件。

问题

我现在有以下内容,但我不确定这是否是正确的方法,主要是因为那个空的 AlgoRunnerProvider 模块。这是实现我想要做的事情的任何其他方式吗?还是为了简化我所拥有的?

我是否应该只创建不同的组件,OneAlgoRunnerComponent 和 TwoAlgoRunnerComponent 并从每个组件中注入(inject)管理器?

构造 Manager 实例的类使用此组件将 AlgoRunner 注入(inject)该实例,以便 Manager 可以将输入传递给它。

@Component(
modules = {
AlgoRunnerProvider.class
}
)
public interface AlgoRunnerComponent {
void inject(Manager manager);
AlgoRunner getAlgoRunner();
}

AlgoRunnerProvider 模块

@Module
public class AlgoRunnerProvider {

@Provides
public AlgoRunner getAlgoRunner() {
return null;
}
}

OneAlgoRunnerProvider,它覆盖了 AlgoRunnerProvider 中的 provides 方法。也可以有一个 TwoAlgoRunnerProvider,它做同样的事情并提供 TwoAlgoRunner,只要它扩展了 AlgoRunner。

public class OneAlgoRunnerProvider extends AlgoRunnerProvider {
private final OneAlgo algo;

public OneAlgoRunnerProvider(OneAlgo algo) {
this.algo = algo;
}

@Override
public OneAlgoRunner getAlgoRunner() {
return new OneAlgoRunner(algo);
}
}

现在所有这些都是这样使用的:

AlgoRunnerComponent build = DaggerAlgoRunnerComponent.builder()
.algoRunnerProvider(new OneAlgoRunnerProvider(new OneAlgo()))
// .algoRunnerProvider(new TwoAlgoRunnerProvider(new TwoAlgo()))
.build();

Manager manager = managerComponent.getManager();
build.inject(manager);

Truth.assertThat(manager.algoRunner).isInstanceOf(OneAlgoRunner.class);
// Truth.assertThat(manager.algoRunner).isInstanceOf(OneAlgoRunner.class);

非常感谢!

最佳答案

dagger 框架用于为您处理对象创建。如果您开始在您希望提供的某个类中进行某种初始化,则可能有一些不符合预期的地方(请参阅 getAlgoRunner())。

如果您想在运行时提供不同的类型,您需要某种工厂来创建正确的对象。输入 Dagger 。

您可以通过多种方式实现您的目标。基本上,模块应该处理对象创建:

@Module
public class AlgoRunnerProvider {

@Provides
public AlgoRunner getAlgoRunner() {
// todo create the correct type
return null;
}
}

1。 @Named 注释(或其他一些Qualifier)

如果您在编译时知道哪个类需要哪个类型,您应该使用限定符。

@Named("Version1")
@Inject
AlgoRunner mRunner;

然后您可以从您的模块中提供不同的实现:

@Provides
@Named("Version1")
public AlgoRunner getAlgoRunner() {
return new Version1AlgoRunner();
}

@Provides
@Named("OtherVersion")
public AlgoRunner getAlgoRunner(Depends someOtherDependency) {
return new OtherVersionAlgoRunner(someOtherDependency);
}

2。运行时切换

虽然您始终可以通过创建具有不同依赖项的多个类来使用第一个选项,但您可能希望能够在运行时进行选择。为此,您需要将一些参数传递给您的模块:

@Module
public class AlgoRunnerProvider {

private final int mType;

public AlgoRunnerProvider(int type) {
mType = type;
}

@Provides
public AlgoRunner getAlgoRunner() {
if(mType == TYPE_A) {
return new Version1AlgoRunner();
} else {
return new OtherVersionAlgoRunner();
}
}
}

使用此变体,您仍然在模块中拥有创建逻辑,您的依赖项来自于此。


3。使用不同的模块

另一种方法是使用不同的模块。如果在编译时确定(不同的类使用不同的模块)而不是在运行时在同一类中的一些选择逻辑,这将只是一个干净的解决方案。

如果您开始编写类似 if typeA then moduleA else moduleB 的代码,您可能应该停下来做些别的事情。

您可以使用相同的组件,但通过使用良好的旧继承,针对不同的类使用不同的模块创建它。每个模块只提供其 AlgoRunner 的实现。

// one class using one module to get a specific behavior
public class MyClassVersionA {

public void onCreate(Bundle saved) {
component.myModule(new MyModuleVersionA()).build();
}
}

// another class using a different module to get a different behavior
public class MyClassSomethingElse {

public void onCreate(Bundle saved) {
component.myModule(new MyModuleSomethingElse()).build();
}
}

然后你可以像这样子类化你的模块

// did not test the following, something like this...
public abstract class MyModule {

@Provides
public AlgoRunner getAlgoRunner();

}

public class MyModuleVersionA extends MyModule {

@Provides
@Override
public AlgoRunner getAlgoRunner() {
return new Version1AlgoRunner();
}
}
public class MyModuleSomethingElse extends MyModule {

@Provides
@Override
public AlgoRunner getAlgoRunner() {
return new SomeOtherAlgoRunner();
}
}

可能还有更多的可能性,特别是如果开始混合使用这些方法,但我认为这 3 种是您可以使用的基本工具。

关于java - Dagger 2 的可交换模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35658488/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com