In an Android project structured to follow the Dependency Inversion Principle (DIP) as outlined in the Android Developer's guide on modularization patterns, I've encountered a challenge with Dagger Hilt dependency injections across modules.
The project's architecture initially mixed public abstractions and private implementations across three modules:
:feature:A
:common:B
:lib:C
To adhere to DIP, the project was restructured into:
:feature:A
:common:B
:lib:C
:feature:A:impl
:common:B:impl
:lib:C:impl
Dagger Hilt is utilized for dependency injection, with all bindings located in the impl
modules. The issue arises when attempting to inject an implementation from :common:B:impl
into :feature:A:impl
, where :common:B:impl
also requires an injection from :lib:C:impl
. While injections work as expected when the implementations and bindings for C
remain in :lib:C
(not fully adhering to DIP), moving them to :lib:C:impl
leads to errors.
The error I encountered is a missing binding error when :common:B:impl
needs to be injected into :feature:A:impl:
/Users/user/AndroidStudioProjects/project/app/build/generated/hilt/component_sources/projectProdDebug/com/project/app/common/app/ProjectApplication_HiltComponents.java:1054: error: [Dagger/MissingBinding] com.project.app.backend.IServiceProviderFromModuleB cannot be provided without an method.
public abstract static class SingletonC implements StatusVerified.StatusVerifiedComponent,
^
com.project.app.backend.IServiceProviderFromModuleB is injected at
[com.project.app.common.app.ProjectApplication_HiltComponents.SingletonC] com.project.appdata.network.DataProviderFromModuleA(serviceProvider, …)
This error suggests that Dagger Hilt cannot find a way to provide an instance of IServiceProviderFromModuleB
for injection, despite the expected setup in the :common:B:impl
module. This scenario typically indicates a misconfiguration or misunderstanding of how Dagger Hilt manages dependencies across modules, especially when adhering to DIP.
I'm seeking insights or solutions to resolve this binding issue, ensuring that the project's structure both adheres to DIP and allows for successful dependency injections across modules using Dagger Hilt.
Does anybody have an idea?
TL;DR:
The issue was caused by having modules with the same name, leading to incorrect Hilt bindings generation - MissingBinding
error. Renaming the module from :lib:C:impl
to :lib:C:impl2
fixed the problem.
This relates to a known Gradle issue: https://github.com/gradle/gradle/issues/847, which was supposedly fixed years ago but seems to have resurfaced.