在使用 Hilt 之前,您应该真正尝试了解 Dagger 的工作原理。因为,Hilt 是建立在 Dagger 之上的!
因此,Dagger 要求您提供依赖关系图。这意味着对于每个可注入的class(使用 Dagger 或 Hilt),您还必须为 Dagger 提供一种方法来创建其依赖项的实例。
考虑到 OP 中发布的场景。我们有,
class DataViewModel(val dataRepository: DataRepository): ViewModel() {
}
&
class DataRepository(val featuresApi: FeaturesApi) {
}
正如您自己指出的那样,featuresApi 是 DataRepository 的依赖项,而 Dagger 无法知道如何创建 FeaturesApi 对象。
现在,Dagger 提供了三种方法来告诉它,如何创建任何类/类型的实例。
@Inject
您可以在您自己的代码中定义的class 的构造函数上使用@Inject 注释来告诉Dagger 如何创建该对象。像这样:
class DataRepository: @Inject constructor(
private val featuresApi: FeaturesApi
)
这将类似于:
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Singleton
@Provides
fun provideDataRepository(): DataRepository {
return DataRepository()
}
}
请注意,在任何给定的 class 中只能有一个单数的 @Inject 带注释的构造函数,因为提供多个 @Inject 带注释的构造函数会混淆 Dagger 使用哪个构造函数。
@Provides
您已经熟悉此注解,可在@Module 中使用注解class。
这个注解通常是为了给 Dagger 提供一种方法来创建对你来说不可编辑的类/类型的实例(通常是库类或由库创建的对象)。在这种情况下,假设您的 FeaturesApi 对象是由 Retrofit(这是 Android 中最流行的网络库)创建的。
所以,通过重写你的 AppModule 类:
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Singleton
@Provides
fun provideFeaturesApi(retrofit: Retrofit): FeaturesApi {
return retrofit.create(FeaturesApi::class.java)
}
}
现在 Dagger 知道如何创建特征 FeaturesApi 对象。
注意:此时,在您的代码中,您会注意到您现在已经引入了 FeaturesApi 的依赖项,即 Retrofit。所以,现在你还必须提供一种方法让 Dagger 知道如何创建Retrofit 实例。否则 Dagger 会向No value passed for parameter 'Retrofit' 抛出类似的错误。
我省略了第三种方式让你弄清楚和研究,因为这与这个问题无关。
补充说明:
- 这些注释(
@InstallIn 除外)与 Hilt 没有任何关系,但实际上由 Dagger 使用。
- 另请注意,访问较低级别对象(在本例中为
DataRepository)的更好方法是通过 interface。