Can the body of a Component be empty in Dagger2?

Viewed 496

I'm learning Dagger and I'm just curious. I understand that if I plan to use Field Injection, I must have something like this:

@Singleton
@Component(modules={AppModule.class, NetModule.class})
 public interface NetComponent {
  void inject(MainActivity activity);
 // void inject(MyFragment fragment);
 }

where I list the classes that will have the field injection.

And also if this component is a parent of other components, I must have something like:

 @Component(modules={ServiceModule.class, 
                ContextModule.class,
                SchedulerModule.class})
 @Singleton
public interface SingletonComponent {
 Context appContext();
 CatTable catTable();
 CatDao catDao();
 CatMapper catMapper();
 CatRepository catRepository();
 CatService catService();
 Retrofit retrofit();
 DatabaseManager databaseManager();
 @Named("MAIN") Scheduler mainThreadScheduler();
 @Named("BACKGROUND") Scheduler backgroundThreadScheduler();
}

But if I don't intend to do either one, can I have something like:

@Singleton
@Component(modules = arrayOf(DatabaseModule::class, AppModule::class,
    ApiServiceModule::class))
 interface AppComponent{

 }

where the body is just empty.

(I'm aware that I will probably need field injection or child components, I just want to be sure that I'm not missing anything).

1 Answers

An entirely empty component (that does not extend another interface) will be useless. Components define entry points into the object graph, so without any methods at all, there's nothing you could do with the object. You've listed members injection methods, but you can also include subcomponent factory methods and builders and component provision methods.

ObjectA getA();    // component provision method
void inject(B b);  // members injection method, which can return void
C inject(C c);     // ...or return the object it injects, for convenience

// You can also make a subcomponent getter, if you supply necessary module instances...
DSubcomponent createD(SomeModule module);
// or just return a builder.
ESubcomponent.Builder createEBuilder();

This is especially important to remember because Dagger will only generate the code for graph bindings accessible from your Component interface. If you have a @Binds or @Provides for ObjectF, ObjectG, or ObjectH, those will not be a part of your Dagger implementation unless they are transitively reachable from the methods you put onto the component interface.


What about components-with-dependencies and subcomponents? A ChildComponent that depends on a ParentComponent will only get access to the objects available through "component provision methods" (zero-arg getters), so a component without methods is still useless. You can also supply an interface (without annotations) and then have your ParentComponent (or any other implementation) passed into the builder. In any case, the available objects are those listed on the parent component's public interface, which still precludes the interface from being empty.

Subcomponents, unlike components-with-dependencies, have their code generated at the same time as the their parents. This means that you don't have to be explicit about what is being inherited from the parent; Dagger can infer what is available in the parent graph. However, as part of their parent, subcomponents also need a reference from the parent component's interface, or else they won't be generated. (This reference can be a factory method that returns the subcomponent, a method that returns the Subcomponent's Builder, or a transitive injection from some other object or members injection on the Component.) Thus, even in the subcomponent case, an empty component is still useless.

Related