我有一门课想通过匕首注射。它需要一个构建器,因为它的一些参数只有在运行时才知道。我也希望这门课能成为单身学生。
也就是说,我们的代码库的几个部分需要这个类的实例,但实际上只有一部分代码库知道如何设置它。
安装在应用程序的早期发生--在任何人实际尝试使用单例之前--但是在Dagger已经初始化了它的根组件之后。
代码的其他部分访问对象的正确方法是什么?
class S {
private S(Foobar foobar) {
// ...
}
@Singleton
public static class Builder {
Foobar foobar;
@Inject
public Builder() {}
public Builder setFoobar(Foobar foobar) {
this.foobar = foobar;
}
public S build() {
return new S(foobar);
}
}
}
class Main {
private Foobar foobar = new Foobar();
private final S s;
@Inject
public Main(S.Builder sBuilder) {
s = sBuilder.setFoobar(foobar).build();
}
}
class Other {
private final S s;
@Inject
public Other(/* What do I put here to get access to S? */) {
}编辑:为了清晰起见,让我声明,本例中的Foobar是在应用程序的早期创建的,但是在Dagger和应用程序的高级结构被实例化之后。这个特定的程序是一个安卓应用程序;在本例中,Foobar是一个膨胀的视图,而S是该视图的控制器。
只有一个Foobar和一个S。我们的代码的各个部分都希望能够与S通信,但实际上只有一部分代码能够创建它。
发布于 2019-11-25 19:16:38
基于我从@MyDogTom的answer中发出的提示,介绍我们的第一个子组件是解决方案。
直到构建了S之后才构建Foobar。然后初始化一个子组件,将S传递给它的生成器,并使用该子组件构造Other。
@Subcomponent
public interface MySubComponent {
@Subcomponent.Builder
interface Builder {
@BindsInstance Builder s(S s);
StatusBarComponent build();
}
/**
* Scope annotation for singleton items within the MySubComponent.
*/
@Documented
@Retention(RUNTIME)
@Scope
@interface MySubComponentScope {}
@MySubComponentScope
Ohter getOther();
}
// Attach MySubComponent to Dagger where appropriate, per their documentation.
// Then, in Main, do something like the following:
class Main {
private final MySubComponent.Builder mySubComponentBuilder;
private final S.Builder sBuilder;
private Foobar foobar;
@Inject
public Main(MySubComponent.Builder mySubComponentBuilder, S.Builder sBuilder) {
this.mySubComponentBuilder = mySubComponentBuilder;
this.sBuilder = sBuilder;
}
// At some point, foobar gets created. Then we call the following method.
private void afterInit();
S s = sBuilder.setFoobar(foobar).build();
Other other = mySubComponentBuilder.s(s).build().getOther();
}
}很明显,这是一个略显做作的例子,但演示了问题的解决方案。
发布于 2019-11-21 10:18:04
您可以将BindsInstance用于https://dagger.dev/api/2.10/dagger/BindsInstance.html
应用程序创建RootComponent。在创建过程中,它应该提供Foobar的实例。让我们看一下伪码
class S {
private S(Foobar foobar) {
// ...
}
public static class Builder {
Foobar foobar;
public Builder() {}
public Builder setFoobar(Foobar foobar) {
this.foobar = foobar;
}
public S build() {
return new S(foobar);
}
}
}
@Module
public static class RootModule {
@Provides
@Singleton
public static S provideS(Foobar foobar) {
return new S.Builder().setFoobar(foobar).build();
}
}
@Singleton
@Component(module = {RootModule.class})
public interface RootComponent {
@Component.Factory
interface Factory {
public RootComponent create(@BindsInstance Foobar foobar)
}
}
public class Application {
private RootComponent createComponent() {
return DaggerRootComponent.factory().create(new Foobar())
}
}更新
这个特定的程序是一个Android应用程序;Foobar在本例中是一个膨胀的视图,S是该视图的控制器。
我强烈建议您不要保留对View的引用。这可能会产生微妙的bug和内存泄漏。相反,我建议您引入某种事件总线,它将是Dagger图中的单例,并在S (视图控制器)和使用者之间共享。这个均匀总线将用于用户与S (视图控制器)之间的通信。
https://stackoverflow.com/questions/58964669
复制相似问题