I'm new to Hilt. I want to provide DataRepository
for ViewModel
. My code in AppModule
is:
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Singleton
@Provides
fun provideDataRepository(): DataRepository {
return DataRepository()
}
}
And then I want to inject it to the constructor of ViewModel like private val dataRepository: DataRepository
but I'm getting No value passed for parameter 'FeaturesApi'
because FeaturesApi
is dependecy of DataRepository
. What I want to do is just simply inject dependency without passing any values. How can I do it?
Before using Hilt you should really try and understand how Dagger works. Since, Hilt is built on top of Dagger!
So, Dagger requires you to provide a dependency graph. Which means for each class
which is injectable (using Dagger or Hilt) you must also provide a way for Dagger to create instances of its dependencies as well.
Considering the scenario posted in the OP. We have,
class DataViewModel(val dataRepository: DataRepository): ViewModel() {
}
&
class DataRepository(val featuresApi: FeaturesApi) {
}
As you have pointed out yourself featuresApi
is a dependency of DataRepository
and Dagger has no way of knowing how to create FeaturesApi
object.
Now, Dagger provides three ways for you to tell it, how to create an instance of any class/type.
@Inject
You can use @Inject
annotation on a constructor of a class
defined in your own code to tell Dagger how to create that object. Like so:
class DataRepository: @Inject constructor(
private val featuresApi: FeaturesApi
)
Which will act similar to:
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Singleton
@Provides
fun provideDataRepository(): DataRepository {
return DataRepository()
}
}
Note that there must only be a singular @Inject
annotated constructor in any given class
, since providing multiple @Inject
annotated constructors will confuse Dagger on which constructor to use.
@Provides
You are already familiar with this annotation which can be used in a @Module
annotated class
.
This annotation is usually reserved to provide Dagger a way to create instances of classes/types which are not editable for you (Usually library classes or objects created by a library). Which in this case will be, assuming your FeaturesApi
object is created by Retrofit
(which is the most popular networking library in Android).
So, by rewriting your AppModule
class a bit:
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Singleton
@Provides
fun provideFeaturesApi(retrofit: Retrofit): FeaturesApi {
return retrofit.create(FeaturesApi::class.java)
}
}
And now Dagger knows how to create a features FeaturesApi
object.
Note: At this point in your code you'd notice that you've now introduced a dependency for FeaturesApi
ie Retrofit
. So, now you must also provide a way for Dagger to know how to create Retrofit
instance. Otherwise Dagger will throw a similar error to No value passed for parameter 'Retrofit'
.
I'm leaving out the third way for you to figure out and study since that is not related to this question.
Further Notes:
@InstallIn
) are in no way related to Hilt but are infact used by Dagger .DataRepository
) is through an interface
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.