DaggerBinds

Additional

Language
Kotlin
Version
1.0.0-alpha1 (Jun 24, 2019)
Created
Jun 4, 2019
Updated
Jun 24, 2019
Owner
EPAM Mobile Lab (epam-mobile-lab)
Contributors
Kirill Rozov (kirich1409)
vladimirzajcev
2
Activity
Badge
Generate
Download
Source code

Commercial

DaggerBinds helper generator

Boilerplate problem

As you know Dagger matches types exactly. Therefore when you would like to provide an implementation of some interface, you should use @Binds annotation. Lest see the example:

interface Service {}

class ServiceImp implements Service {

    @Inject
    ServiceImp()
}

Now we have possibility to inject ServiceImp, but have no possibility to inject Service. To have that possibility we need to create Dagger Module like this:

@Module
interface BindsModule {

    @Binds
    Service bindService(ServiceImp service)
}

That approach requires writing a large number of boilerplate code.

Solution

We propose to generate Generated_BindsModule based on Java Annotation Processor (APT).

Usage of DaggerBinds

In order to use DaggerBinds library a few simple steps should be done:

  • Mark corresponding Classes with @BindTo annotation:
interface Service {}

@BindTo(interfaceType = Service.class)
public class ServiceImp implements Service {

    @Inject
    ServiceImp()
}
  • Add generated module to the root (app) component:
@Component(modules = {Generated_BindsModule.class})
public interface RootComponent {

    Service service();
}

Generated Generated_BindsModule module will be:

@Module
public interface Generated_BindsModule {
  @Binds
  Service binds_com_epam_subtypes_single_ServiceImp(ServiceImp com_epam_subtypes_single_ServiceImp);
}

Usage of Qualifiers

In order to be able to use multi binds DaggerBinds supports 'javax.inject.Named' and your own 'qualifier annotation'. Let see how to use qualifiers annotation:

  • Usage of @Named qualifier annotation:
@BindTo(interfaceType = Repository.class, qualifier = Named.class)
public class RepositoryImpFirst implements Repository {
}

Generated Generated_BindsModule module will be:

@Module
public interface Generated_BindsModule {
  @Binds
  @Named("com.epam.subtypes.severalfirst.RepositoryImpFirst")
  Repository binds_com_epam_subtypes_severalfirst_RepositoryImpFirst(RepositoryImpFirst com_epam_subtypes_severalfirst_RepositoryImpFirst);
}
  • Usage of your own Qualifier annotation:
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ServiceImpQFirst {
}

@BindTo(interfaceType = Service.class, qualifier = ServiceImpQFirst.class)
public class ServiceImpFirst implements Service {
}

Generated Generated_BindsModule module will be:

@Module
public interface Generated_BindsModule {
  @Binds
  @ServiceImpQFirst
  Service binds_com_epam_subtypes_severalfirst_ServiceImpFirst(ServiceImpFirst com_epam_subtypes_severalfirst_ServiceImpFirst);
}

Download

Gradle dependency:

dependencies {
    implementation 'com.epam.daggerbinds:dagger-binds-annotations:1.0.0-alpha1'
    annotationProcessor 'com.epam.daggerbinds:dagger-binds-processor:1.0.0-alpha1'
}

If you are using Kotlin, replace annotationProcessor with kapt. Nevertheless using kapt has one limitation for now. Please see limitations below.

Current limitations

  • For the proper work minimum dagger version should be 2.11.
  • DaggerBinds doesn't support work with own qualifier annotation with parameters for now.
  • In case of kapt usage generated module should be specified in the dagger's [Module] annotation with full name, e.g.
@Component(modules = [com.epam.daggerbinds.bindto.Generated_BindsModule::class])
interface RootComponent {
    fun service(): Service
}