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

How can I use Hilt to inject Retrofit to Repository, which is injected to ViewModel?

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

我想将 ViewModel 注入 Fragment。该片段包含在 Activity 中。现在,我已经将注释添加到 ApplicationActivityFragment

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

可以看出,我的HomeFragment依赖于HomeViewModel。我像这样添加了一个ViewModel injection as described here

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

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

class MovieRepository (private val movieApi: MovieService) {
    ...
}

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

interface MovieService {
    ...
}

为了获取我的 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!!
            }
        }
}

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

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

您必须先定义binding information to Hilt. Binding information tells Hilt how to provide the instances of the dependency specified. Because MovieService is created using a Retrofit (which is a 3rd-party class not created by yourself) using the builder pattern, you can't use the constructor injection and you have to instead use Hilt modules and the annotation @Provides to tell Hilt about this binding information

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

• The function return type tells Hilt what type the function provides instances of.

• The function parameters tell Hilt the dependencies of the corresponding type.

• The function body tells Hilt how to provide an instance of the corresponding type. Hilt executes the function body every time it needs to provide an instance of that type.

最后只需要修改MovieRepositoryclass,为每个repository添加一个module,并注解告诉Hilt如何提供Retrofit创建的服务实例的函数@Provides.

代码。

class MovieRepository @Inject constructor(
    private val movieApi: MovieService
) {
    ...
}
interface MovieService {
    ...
}

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

如您所见,ActivityRetainedComponent@InstallIn 注释中被引用,因为 Repository 将被注入到 ViewModelEach Android component is associated to different Hilt components.