我试图通过使用描述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();
}
}
似乎Component从父组件获得A
,这不是我想要的,我的代码问题在哪里?
请注意,“封装子组件”页面中的示例使用qualifier annotation,@PrivateToDatabase
,它不是范围注释,它区分Database
与@PrivateToDatabase Database
绑定的绑定。
子组件从其父组件继承所有绑定,因此您当前从父组件获得A,并且子组件中也可以使用A.如果你的子组件中的任何东西需要注入A,如果它没有标记为@Singleton
,那么这尤其棘手:你想要父组件中的A,还是子组件中的A?
这种情况的另一个棘手的部分是你不能在使用@Inject
构造函数的类上使用限定符注释。
我建议您执行以下操作:
@Provides
方法从子组件获取A实例。如果您不想提取接口,您也可以通过从A中删除@Inject
并在子组件中的模块中写入@Provides
方法来解决此问题,该模块返回合格的A,因此不合格的A通过顶级组件且合格的A仅在子组件中可用。