使用子组件进行封装时的无限递归

时间:2019-04-26 11:08:23

标签: dagger

我正在尝试使用描述为here的子组件来实现封装,但是得到了无限递归。

这是我的代码:

//tried adding @ScopeA, still the same.
public class A {
    @Inject
    A(B b) {

    }
}

@ScopeA
public class B {
    @Inject
    B() {

    }
}
@Component(modules = AModule.class)
@Singleton
public interface AComponent {
    public A a();
}
@Module(subcomponents = SComponent.class)
class AModule {
    @Provides
    @Singleton
    A a(SComponent.Factory factory) {
        return factory.component().a();
    }
}
@Subcomponent
@ScopeA
interface SComponent {
    @ScopeA
    A a();
    @Subcomponent.Factory
    interface Factory {
        SComponent component();
    }
}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerAComponent.create().a();
    }
}

检查生成的匕首代码后,我发现了这一点:


  private final class SComponentImpl implements SComponent {
    private SComponentImpl() {}

    @Override
    public A a() {
      return DaggerAComponent.this.aProvider.get();
    }
  }

似乎SComponent正在从父组件获取A,这不是我想要的,我的代码在哪里呢?

1 个答案:

答案 0 :(得分:1)

请注意,“封装的子组件”页面中的示例使用qualifier annotation@PrivateToDatabase,这不是作用域注释,并且将Database的绑定与{{ 1}}。

子组件从其父组件继承所有绑定,因此您当前确实从父组件获得了A,并且从子组件获得了A。如果子组件中的任何内容需要注入A,而没有标记@PrivateToDatabase Database,则这特别棘手:您要从父组件中获取A,还是从子组件中获取A?

这种情况的另一个棘手的部分是,您不能在使用@Singleton构造函数的类上使用限定符注释。

我建议您执行以下操作:

  1. 从A提取一个接口,这样便有了A和AImpl。
  2. 保留从子组件获取A实例的@Inject方法。
  3. 让子组件公开AImpl,并且(为了避免歧义)仅将AImpl插入子组件的类中,而不是A。

如果您不想提取接口,也可以通过从A中删除@Provides并在返回合格A的子组件的模块中编写@Inject方法的方法来解决此问题,因此,不合格的A通过顶级组件,而合格的A仅在子组件中可用。