Android多模块场景下,Dagger能否实现依赖动态替换?如何实现?
This is a classic dependency inversion use case, and Dagger is built to handle scenarios exactly like this—let me walk you through the step-by-step setup to make it work.
Step 1: Define an Abstract Interface in the Core Module
First, we need to decouple class A from the concrete B by introducing an interface. This lets A depend on an abstraction instead of a specific implementation.
// Core module - Define the interface public interface BusinessLogic { void execute(); } // Core module - Default implementation (B) public class B implements BusinessLogic { @Override public void execute() { // Core's default behavior here System.out.println("Executing default logic from B"); } }
Step 2: Update Class A to Depend on the Interface
Modify A in the Core module to inject the interface instead of the concrete B. This is the core of the dependency inversion principle.
// Core module public class A { private final BusinessLogic businessLogic; @Inject // Let Dagger handle injection of BusinessLogic public A(BusinessLogic businessLogic) { this.businessLogic = businessLogic; } public void runLogic() { businessLogic.execute(); // Uses whichever implementation is provided } }
Step 3: Configure Core Module's Dagger Setup for Default Behavior
In the Core module, create a Dagger Module that provides the default B implementation, but allows the App module to override it using optional bindings.
// Core module @Module public abstract class CoreModule { // Declare that BusinessLogic can have an optional override from upper modules @BindsOptionalOf abstract BusinessLogic bindOptionalBusinessLogic(); // Provide the final BusinessLogic: use App's implementation if exists, else B @Provides static BusinessLogic provideBusinessLogic( Optional<BusinessLogic> optionalLogic, B defaultLogic) { return optionalLogic.orElse(defaultLogic); } }
Step 4: Add App Module's Override Implementation (Class C)
In the App module, create your custom C class that implements the same BusinessLogic interface, then create a Dagger Module to provide this implementation.
// App module - Custom implementation (C) public class C implements BusinessLogic { @Override public void execute() { // App-specific behavior here System.out.println("Executing custom logic from C"); } } // App module - Dagger module to provide C @Module public abstract class AppModule { @Binds abstract BusinessLogic bindAppBusinessLogic(C c); }
Step 5: Assemble the Dagger Component in the App Module
Create a Dagger Component in the App module that includes both the Core and App modules. This tells Dagger to merge the bindings—using the App's C implementation if available, falling back to Core's B if not.
// App module @Component(modules = {CoreModule.class, AppModule.class}) public interface AppComponent { A getA(); // Expose A so you can inject it into your App's classes // If you need to inject directly into Activities/Fragments, add inject methods here // void inject(MainActivity activity); }
How It Works
- When the App module includes
AppModule, Dagger will detect theBusinessLogicbinding fromCand use that inA. - If you remove
AppModulefrom the Component's modules, Dagger will fall back to the defaultBimplementation from the Core module.
Key Notes
- Use
@Bindsinstead of@Providesfor interface-implementation bindings—it's more efficient and cleaner. @BindsOptionalOfis Dagger's way of allowing optional overrides without causing duplicate binding errors.- If you're using Kotlin, you can replace Java's
Optionalwith a nullable type (BusinessLogic?) for more idiomatic code.
内容的提问来源于stack exchange,提问作者wojciech.osak

