简体   繁体   English

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

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

I have just learnt manual dependency injection, but I am trying out Hilt to handle these dependency injections.我刚刚学习了手动依赖注入,但我正在尝试使用 Hilt 来处理这些依赖注入。

I want to inject a ViewModel into a Fragment .我想将ViewModel注入Fragment The fragment is contained within an Activity .该片段包含在Activity中。 Right now, I have added the annotations to Application , Activity , and Fragment .现在,我已将注释添加到ApplicationActivityFragment

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

As can be seen, my HomeFragment depends on HomeViewModel .可以看出,我的HomeFragment依赖于HomeViewModel I have added a ViewModel injection as described here like so.我已经添加了一个ViewModel 注入,如此处所述

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

However, the ViewModel requires two repositories.但是, ViewModel需要两个存储库。 Right now, my MovieRepository is like so.现在,我的MovieRepository就是这样。

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

In the above code, MovieService will be created by Retrofit using the Retrofit.create(class) method.在上面的代码中, MovieService将由 Retrofit 使用Retrofit.create(class)方法创建。 The interface used to create MovieService is like so.用于创建MovieService的接口是这样的。

interface MovieService {
    ...
}

To get my Retrofit instance, I am using the following code.要获取我的 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!!
            }
        }
}

I am not too sure how I can inject the Retrofit into the Repository to be used by my ViewModel later on.我不太确定如何将 Retrofit 注入存储库以供我的ViewModel稍后使用。 Could someone give me some pointers or step-by-step instructions on how to do this?有人可以给我一些关于如何执行此操作的指示或分步说明吗?

Apparently, it is not as hard as it seems.显然,它并不像看起来那么难。

You have to first define the binding information to Hilt.您必须先定义 Hilt 的绑定信息 Binding information tells Hilt how to provide the instances of the dependency specified.绑定信息告诉 Hilt 如何提供指定依赖项的实例。 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 .因为MovieService是使用构建器模式使用 Retrofit(这是一个不是您自己创建的第三方 class)创建的,所以您不能使用构造函数注入,而必须改用Hilt 模块注解@Provides告诉 Hilt 关于这个绑定信息

As described in the doc, the annotated function in the Hilt module you have created will supply the following information to Hilt so that Hilt can provide the instances of the dependency.如文档中所述,您创建的 Hilt 模块中带注释的 function 将向 Hilt 提供以下信息,以便 Hilt 可以提供依赖项的实例。

• The function return type tells Hilt what type the function provides instances of. • function 返回类型告诉 Hilt function 提供的实例是什么类型。

• The function parameters tell Hilt the dependencies of the corresponding type. • function 参数告诉Hilt 相应类型的依赖项。

• The function body tells Hilt how to provide an instance of the corresponding type. • function 正文告诉Hilt 如何提供相应类型的实例。 Hilt executes the function body every time it needs to provide an instance of that type.每次需要提供该类型的实例时,Hilt 都会执行 function 主体。

In the end, you only need to modify the MovieRepository class, add a module for each repository, and annotate the function that tells Hilt how to provide the service instance created with Retrofit with @Provides .最后只需要修改MovieRepository class,为每个repository添加一个module,在function注解告诉Hilt如何为Retrofit创建的服务实例提供@Provides

Code.代码。

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)
}

As you can see, the ActivityRetainedComponent is referred in the @InstallIn annotation because the Repository is to be injected to a ViewModel .如您所见, @InstallIn注释中引用了ActivityRetainedComponent ,因为 Repository 将被注入到ViewModel中。 Each Android component is associated to different Hilt components . 每个 Android 组件都关联到不同的 Hilt 组件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM