如何使用 Hilt 将 Retrofit 注入到注入到 ViewModel 的 Repository?

Ric*_*ard 1 android dependency-injection dagger-2 retrofit2 dagger-hilt

我刚刚学习了手动依赖注入,但我正在尝试使用 Hilt 来处理这些依赖注入。

我想将 a 注入ViewModelFragment. 该片段包含在Activity. 现在,我已经添加了注解ApplicationActivityFragment

@HiltAndroidApp
class MovieCatalogueApplication : Application()
Run Code Online (Sandbox Code Playgroud)
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    ...
}
Run Code Online (Sandbox Code Playgroud)
@AndroidEntryPoint
class HomeFragment : Fragment() {
    private lateinit var binding: FragHomeBinding
    private val viewmodel: HomeViewModel by viewModels()
    ...
Run Code Online (Sandbox Code Playgroud)

可以看出,我的HomeFragment依赖于HomeViewModel. 我已经添加了一个ViewModel 注入,如此处所述。

class HomeViewModel @ViewModelInject constructor(
    private val movieRepository: MovieRepository,
    private val showRepository: ShowRepository,
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {
    ...
}
Run Code Online (Sandbox Code Playgroud)

但是,ViewModel需要两个存储库。现在,我的MovieRepository就是这样。

class MovieRepository (private val movieApi: MovieService) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,MovieService会使用 Retrofit 创建的Retrofit.create(class)方法。用来创建的界面MovieService是这样的。

interface MovieService {
    ...
}
Run Code Online (Sandbox Code Playgroud)

为了获得我的 Retrofit 实例,我使用了以下代码。

object RetrofitService {
    ...
    private var _retrofit: Retrofit? = null
    val retrofit: Retrofit
        get() {
            return when (_retrofit) {
                null -> {
                    _retrofit = Retrofit.Builder()
                        .client(client)
                        .baseUrl(BASE_URL)
                        .addConverterFactory(GsonConverterFactory.create())
                        .build()
                    _retrofit!!
                }
                else -> _retrofit!!
            }
        }
}
Run Code Online (Sandbox Code Playgroud)

我不太确定如何将 Retrofit 注入 Repository 以供我ViewModel以后使用。有人可以给我一些有关如何执行此操作的指示或分步说明吗?

Ric*_*ard 5

显然,这并不像看起来那么难。

您必须首先定义Hilt的绑定信息。绑定信息告诉 Hilt 如何提供指定的依赖项的实例。因为MovieService是使用构建器模式使用 Retrofit(不是您自己创建的第 3 方类)创建的,所以不能使用构造函数注入,而必须使用Hilt 模块注解@Provides来告诉 Hilt 此绑定信息.

如文档中所述,您创建的 Hilt 模块中的注释函数将向 Hilt 提供以下信息,以便 Hilt 可以提供依赖项的实例。

• 函数返回类型告诉 Hilt 函数提供什么类型的实例。

• 函数参数告诉 Hilt 相应类型的依赖关系。

• 函数体告诉 Hilt 如何提供相应类型的实例。每次需要提供该类型的实例时,Hilt 都会执行函数体。

最后只需要修改MovieRepository类,为每个存储库添加一个模块,并在告诉 Hilt 如何提供 Retrofit 创建的服务实例的函数中添加注解@Provides

代码。

class MovieRepository @Inject constructor(
    private val movieApi: MovieService
) {
    ...
}
Run Code Online (Sandbox Code Playgroud)
interface MovieService {
    ...
}

@Module
@InstallIn(ActivityRetainedComponent::class)
object MovieModule {
    @Provides
    fun provideMovieService(): MovieService
        = RetrofitService.retrofit.create(MovieService::class.java)
}
Run Code Online (Sandbox Code Playgroud)

如您所见,注解中ActivityRetainedComponent引用了 ,@InstallIn因为 Repository 将被注入到ViewModel. 每个 Android 组件都与不同的 Hilt 组件相关联