Bernardo Cunha
Bernardo Cunha

Reputation: 443

What should go in the "injects" in a Dagger @Module?

Guice user, trying to understand a bit of the benefits of Dagger here.

Let's say I have the following

MyActivity.java
---------------
public class MyActivity {
  @Inject MyImplicitClass myImplicitClass;
  @Inject @Named("foo") MyExplicitClass myNamedExplicitClass;
  ...
}

MyImplicitClass.java
------------
public class MyImplicitClass {
   @Inject
   MyImplicitClass(MyExplicitClass myExplicitClass) {
     ...
   }
   ...
}

MyModule.java
---------------
@Module(injects = { ? }) {
  @Provides provideExplicitClass() {
    return new MyExplicitClass();
  }
  @Named("foo") @Provides provideNamedExplicitClass() {
    return new MyExplicitClass();
  }
}

So, my question is, what should go in the Injects?

I know for a fact that MyActivity needs to go. Or rather, whatever "this" needs to have DaggerInjector.inject(this)

Does anything else? Would Dagger the implicit construction injection class (MyImplicitClass) and/or the class explicitly provided in the module (MyExplicitClass) to also be specified?

MyExplicitClass wouldn't even make sense if I need it to be annotated.

However, the javadoc makes me feel I should error the side of inclusion http://square.github.io/dagger/javadoc/dagger/Module.html#injects()

Upvotes: 3

Views: 2705

Answers (1)

Miguel
Miguel

Reputation: 20123

Dagger 1 does it's validation at compile therefore it needs all of the entry point you're going to use at runtime (objectgraph.get(entrypoint), objectgraph.inject(entrypoint)).

Entry points are the injectable classes which are at the top of the dependency graph. In Android most of the time those are your Activities, Fragments, Services, Broadcast Receivers. All compontents which are not created by Dagger. You would also list classes which are not part of any entry point's dependency tree again becoming an entry point of their own.

Those entry point are use to do validation by Dagger. Dagger will start validation at the entry points and tricle down the dependency tree and validate dependencies annotated with @Inject and @Provides from your Modules.

So in conclusion only entry points needs to be provided in the @Module(injects = { * })

In your example because the MyImplicitClass is an @Inject dependency of your entry point MyActivity you don't need to specify it in the @Modules(injects={}). The same is true for your MyExplicitClass dependency. Therefore from your example the only class that needs to be added to the list is in fact MyActivity.

Base on your example code, if you had something like this.

// MyIndependantClass.java
-----------------
public class MyIndependantClass {
    @Inject
    MyIndependantClass(MyExplicitClass myExplicitClass) {
    }
}

// MyActivity.java
---------------
public class MyActivity {
  @Inject MyImplicitClass myImplicitClass;
  @Inject @Named("foo") MyExplicitClass myNamedExplicitClass;
  ...

  protected void onCreate (Bundle savedInstanceState) {
    MyIndependantClass myIndependantClass = MyObjectGraph.get(MyIndependantClass.class);
    ...
  }
}

The fact that MyIndependantClass is created using ObjectGraph.get() and is not a direct dependency of your MyActivity entry point you would need to declare that class part of the injects list.

// MyModule.java
---------------
@Module(injects = { MyActivity.class, MyIndependantClass.class }) {
  @Provides provideExplicitClass() {
    return new MyExplicitClass();
  }
  @Named("foo") @Provides provideNamedExplicitClass() {
    return new MyExplicitClass();
  }
}

Upvotes: 4

Related Questions