Reputation: 2825
I want to inject into Activity object that has nested dependency. All dependencies are managed by Dagger module.
I've tried to do it for three different way. For me the best is method third, which actually throws me an error, which I don't fully understand.
Can you explain me why third method isn't working?
public class Bar {
public void bar() {
Log.i("Bar", "bar");
}
}
public class MainActivity extends Activity {
@Inject
Foo foo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ObjectGraph.create(new MainModule()).inject(this);
ButterKnife.inject(this);
}
@OnClick(R.id.button)
void onButtonClick() {
foo.foo();
}
}
First method is working - Foo is implementation of an interface:
public interface IFoo {
public void foo();
}
public class Foo implements IFoo{
@Inject
Bar bar;
@Override
public void foo() {
bar.bar();
}
}
@Module(injects = MainActivity.class, library = true)
public class MainModule {
@Provides
@Singleton
Bar provideBar() {
return new Bar();
}
@Provides
@Singleton
IFoo provideFoo(Foo foo) {
return foo;
}
}
Second method is working - Foo is normal class but module doesn't contains it:
public class Foo {
@Inject
Bar bar;
public void foo() {
bar.bar();
}
}
@Module(injects = MainActivity.class)
public class MainModule {
@Provides
@Singleton
Bar provideBar() {
return new Bar();
}
}
Third method throws an error - Foo is normal class and module contains it:
Error:(12, 8) error: Unknown error java.lang.IllegalStateException thrown by javac in graph validation: Dependency cycle:
0. foo.Foo bound by @Singleton/ProvidesBinding[key=foo.Foo method=foo.MainModule.provideFoo()
0. foo.Foo
public class Foo {
@Inject
Bar bar;
public void foo() {
bar.bar();
}
}
@Module(injects = MainActivity.class, library = true)
public class MainModule {
@Provides
@Singleton
Bar provideBar() {
return new Bar();
}
@Provides
@Singleton
Foo provideFoo(Foo foo) {
return foo;
}
}
Upvotes: 2
Views: 1621
Reputation: 40193
This provider method creates a cycle:
@Provides
@Singleton
Foo provideFoo(Foo foo) {
return foo;
}
You need an instance of Foo
to create an instance of Foo
, so you can never obtain an instance.
Proposed solution:
public class Foo {
private final Bar bar;
@Inject
public Foo(Bar bar) {
this.bar = bar;
}
public void foo() {
bar.bar();
}
}
@Module(injects = MainActivity.class, library = true)
public class MainModule {
@Provides
@Singleton
Bar provideBar() {
return new Bar();
}
@Provides
@Singleton
Foo provideFoo(Bar bar) {
return new Foo(bar);
}
}
Upvotes: 3