Compiler Options

fastInit mode

You can choose to generate your Dagger @Components in a mode that prioritizes fast initialization. Normally, the number of classes loaded when initializing a component (i.e., when calling DaggerFooComponent.create() or DaggerFooComponent.builder()...build()) scales with the number of bindings in the component. In fastInit mode, it doesn’t. There are tradeoffs, however. Normally, each Provider you inject only holds a reference to providers of all its transitive dependencies; in fastInit mode, each Provider holds a reference to the entire component, including all scoped instances. This means that in fastInit mode, holding/leaking a Provider is equivalent to holding/leaking the entire component, which is usually a much larger set of objects than just the scoped dependencies of the Provider in the default mode.

You should evaluate this tradeoff for your application when choosing to build in fastInit mode, particularly if you are aware of cases where your application intentially holds a Provider beyond the lifetime of the component. Take care to measure your application’s startup time with and without fastInit mode to see how much benefit it has for your users. (Please let us know whether it’s working for you!)

In general, for environments like Android where Dagger initialization is often on the user’s critical path and where class loading is expensive, fastInit mode is likely the correct choice. The main drawback of fastInit mode means that it is easier to leak a Context like the activity with a leaked Provider, but for unintentional cases, those are leaks that should be fixed anyway and those leaks would always have the potential to have grow dependencies on the activity as the codebase changes (thereby leaking it in the default mode as well).

To enable fastInit mode, pass the following option to javac when building your Dagger @Component: -Adagger.fastInit=enabled. Note that if you are using the Hilt Gradle Plugin in your project, fastInit mode will already be enabled by default.

Turning on code formatting

Using -Adagger.formatGeneratedSource=enabled will cause Dagger’s generated sources to be formatted according to google-java-format. However, by default this option is disabled because it can lead to noticable build performance issues.

In most cases, the default formatting should be very readable, but you might prefer to enable this option in production code or continuous integration tests to make stack traces easier to interpret (since the unformatted source may squeeze more things on the same line).

Note: Formatting of a 143k line file generated by Dagger (one of the largest at Google!) took between 2.6 and 3 seconds in a benchmarking test. As with all optimizations, verify the effects on your machine/environment.

Full binding graph validation

By default, problems among the bindings in a module or subcomponent or component don’t get reported unless they are used as part of a whole component tree rooted at a root @Component or @ProductionComponent. However, if you pass -Adagger.fullBindingGraphValidation=ERROR or -Adagger.fullBindingGraphValidation=WARNING to javac, then all the bindings of each module, subcomponent, and component will be checked, including those that aren’t used. Any binding graph errors, such as duplicate bindings, will be reported at the module, subcomponent, or component. (Note that missing bindings will not be reported for full binding graphs unless they’re also found when analyzing the binding graph that’s actually used to generate the root component.)

If full binding graph validation is turned on, SPI implementations will see a BindingGraph representing the bindings for each module, component, and subcomponent as well.

Ignore wildcards in keys of provisioned bindings

The dagger.ignoreProvisionKeyWildcards flag is disabled be default, but it can be enabled by passing the -Adagger.ignoreProvisionKeyWildcards=ENABLED annotation processing option during compilation.

When enabled, Dagger’s annotation processor will no longer allow provisioning two bindings that only differ by the wildcards in their types. For example, consider the module below:

@Module
interface MyModule {
  @Provides Foo<Bar> provideFooBar() { ... }
  @Provides Foo<? extends Bar> provideFooExtendsBar() { ... }
}

When dagger.ignoreProvisionKeyWildcards is disabled MyModule will result in the creation of two separate bindings: Foo<Bar> and Foo<? extends Bar>.

However, when dagger.ignoreProvisionKeyWildcards is enabled MyModule will result in a [Dagger/DuplicateBindings] error because Foo<Bar> and Foo<? extends Bar> are considered duplicate bindings since they only differ by the wildcards in their type.

In general, we recommend enabling this flag because it can be error prone to have multiple bindings that only differ by the wildcards in their type. This is especially true when dealing with Kotlin sources, where wildcards must be interpreted indirectly from a number of factors other than the explicit variance at the use site.