From the elaboration in the comments:
I am trying constructor injection to achieve dependency. ClassA depends on ClassB. And ClassB has parameter constructor, say ClassB(int param). This parameter is provided at runtime, so my confusion is how dagger is able to create object B.
If B's param is the same every time, across your object graph
This might be the case if your param is a key, ID, or other configuration setting. If so, you can use a @Provides
method in a Module to teach Dagger how to provide a ClassB object when you ask for one.
@Module
public abstract class YourModule {
@Provides static ClassB provideClassB() {
return new ClassB(/* your constant here */);
}
}
Because @Provides
methods can take parameters that come from the object graph, you can even get your value from somewhere else:
@Module
public abstract class YourModule {
@Provides static ClassB provideClassB(SomeDependendency someDep) {
return new ClassB(someDep.getParameterForClassB());
}
}
If B only takes custom parameters
This might be the case if your ClassB is a data object or disposable object, especially if you don't need to replace ClassB for testing. (Don't mock data objects.) If all of that is true, then ClassB doesn't need to be a part of your object graph. Call the constructor directly.
ClassB myB = new ClassB(someParameter);
Sometimes this distinction is called injectables versus newables: If you have complicated and interconnected classes that need to access one another, you have an injectable, and references to it should be provided externally. If you have a tightly-contained class that doesn't need substitution, you have a newable, and can call the constructor or static factory method directly.
If B has injected parameters AND constructor parameters
In some cases, a class like ClassB needs both one-off constructor parameters and injected parameters from the graph at the same time. Though this might be a subtle hint that the class is doing too much, there are common workarounds that combine those two inputs into the same list of constructor parameters. This is known as assisted injection, and allows for the creation of factory objects where the DI framework provides the factory and you use it to get the value you want.
/* in ClassB */ public ClassB(DepA a, DepB b, int param) { /* ... */ }
/* ClassBFactory */
public ClassBFactory {
Provider<DepA> depAProvider;
Provider<DepB> depBProvider;
public ClassBFactory(
Provider<DepA> depAProvider,
Provider<DepB> depBProvider) {
/* set depAProvider and depBProvider */
}
public ClassB get(int param) {
return new ClassB(depAProvider.get(), depBProvider.get(), param);
}
}
Because this is similar boilerplate-generation to Dagger, but more reusable in other dependency injection frameworks, Dagger recommends the Google project AutoFactory to generate that implementation based on inspecting the dependencies and classes. You'll need to add some annotations to ClassB to get that to work, but it will allow you to distinguish between graph-provided deps and one-off deps, and insulate you from having to change constructor calls if your dep list changes.