Dagger Reflect - sergei-lapin/pimp-my-gradle-recipes GitHub Wiki

Dagger Reflect is a nice way to, not without a compromise, boost annotation processing speed for your project.

Originally it is a library by Jake Wharton who is well known in Android dev community as a great specialist and libraries creator.

The core idea is to replace original dagger library and dagger compiler with reflection based analogues to boost the performance of day-to-day developer builds

Before you start, make sure that all of your Dagger components are created either via @Component.Factory or @Component.Builder, and that you custom Dagger related annotation classes @Qualifier, @MapKey, etc. are using RUNTIME retention

The library itself is offering two approaches:

  • Partial reflection
  • Full Reflection

Partial reflection

  • Doesn't require code modification
  • Generates component realisations that are basically proxy to reflection calls

Full reflection

  • Requires code modification
  • Complete skip of Dagger annotation processing

Applying to your project

From this point I'll focus on partial reflection approach as it seems more appropriate for day-to-day usage

Well, if we'd look at library's recommended way of applying it to your project dependencies

dependencies {
  if (properties.containsKey('android.injected.invoked.from.ide')) {
    debugAnnotationProcessor 'com.jakewharton.dagger:dagger-reflect-compiler:0.3.0'
    debugApi 'com.jakewharton.dagger:dagger-reflect:0.3.0' // or debugImplementation
  } else {
    debugAnnotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
  }
  releaseAnnotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
  api "com.google.dagger:dagger:$daggerVersion" // or implementation
}

er... It doesn't seem quite nice. And one might ask: is there a better way? Of course there is. Introducing Delect plugin, that requires you to only add few lines to root project's build.gradle file

buildscript {
  classpath 'com.soundcloud.delect:delect-plugin:0.3.0'
}
apply plugin: 'com.soundcloud.delect'

And add dagger.reflect=true to your local ~/.gradle/gradle.properties file — you're done. Now your local builds will use dagger reflect under the hood. In case you need to run build without dagger reflect only once you could invoke it like that ./gradlew taskName -Pdagger.reflect=false.

Cons of using Dagger Reflect are pretty obvious:

  1. Compile time DI graph validation is gone
  2. A bit of impact on app's runtime performance

Despite the cons, main advantage that you get is ~75% speed up of your annotation processing (at least it was the case for projects that I've applied it to). And of course you shouldn't deliver it as a part of your production code and only use it for better engineer experience during day-to-day work