I have two data source class, LocalDataSource and RemoteDataSource. In DataRepository, I need both the classes but on need basis. I don't want to inject both the classes in DataRepository constructor. Instead want to overload constructor with single data source class. How to implement this with dagger?
To directly answer the question: Dagger supports one @Inject
constructor at most. You can use a @Provides
method to call any constructor or factory method you'd like, but if you want Dagger to manage your dependencies it will only read the single constructor you specify with @Inject
. That said, that's not quite the right solution here in any case.
If your class needs a LocalDataSource or a RemoteDataSource, and you don't know which one until runtime, inject a Provider<LocalDataSource>
and Provider<RemoteDataSource>
(or Lazy<LocalDataSource>
and Lazy<RemoteDataSource>
). These objects are inexpensive Dagger-implemented abstractions over your LocalDataSource and RemoteDataSource constructors, which Dagger automatically allows you to inject: For any T
available in your graph, you can inject Provider<T>
and Lazy<T>
(or even Provider<Lazy<T>>
, as described in the documentation).
In this way, Provider
and Lazy
can help you avoid creating either DataSource instance until you know which one you need.
The difference between them is that Lazy<T>
will locally cache the object instance, acting like a field in your class. Provider<T>
will always consult your Dagger Component, which will in most cases will return you a newly-allocated object unless you've applied a scope like @Singleton
. If your objects are expensive to construct, Lazy is a good choice, since you'll only request one instance across the lifetime of your consumer; if they are cheap to construct, then you might even choose to use a Provider within a method and letting your object be garbage-collected as soon as it is no longer needed.
Of course, as Steven and AlphaOne point out in the comments, you might also consider a design where your DataRepository consumer accepts an arbitrary DataSource that you or Dagger can provide. This generally makes sense, as DataSource is likely a useful interface and DataRepository might not need to know implementation details of the source it consults. However, if you need to handle an arbitrary source specification at runtime, at some point you'll still need to inject both a @Local DataRepository
and @Remote DataRepository
(assuming you've created @Qualifier
annotations @Local
and @Remote
), and at that point it makes even more sense to use a Provider/Lazy instead of creating both DataRepository objects and their respective DataSources.