是否可以创建同一对象的不同实例并通过将参数传递给 Koin 中的 get() 函数来访问它们?
Posted
技术标签:
【中文标题】是否可以创建同一对象的不同实例并通过将参数传递给 Koin 中的 get() 函数来访问它们?【英文标题】:Is it possible to create different instances of the same object and access them by passing parameters to get() function in Koin? 【发布时间】:2022-01-16 18:03:46 【问题描述】:我正在使用 Koin 作为我的应用程序的 DI。我创建了一个模块:
object NetworkModule
fun get() = module
single
val authenticationInterceptor = Interceptor chain ->
// Request customization goes here
OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.addInterceptor(authenticationInterceptor) //Not all clients might have this interceptor
.build()
single
Retrofit.Builder()
.baseUrl("example.com")
.client(get(/* I would like to send some paramter here */))
.addConverterFactory(GsonConverterFactory.create(get()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(Api::class.java)
如何创建具有不同参数集或具有不同实例化的不同HttpClient
或Retrofit
实例?例如,在某些情况下,我可能需要 OkHttpClient
和 AutheniticationInterceptor
,而在其他一些情况下,我的客户可能不需要使用它。
可以在调用get()
的时候传递一些参数,这样就可以得到不同的实例吗?任何建议都会受到重视。
【问题讨论】:
【参考方案1】:您可以使用命名属性 - 例如
single<OkHttpClient>(named("auth"))
// here you pass the version with authinterceptor
single<OkHttpClient>(named("noAuth"))
// here you pass the version without authinterceptor
然后在您的 get() 方法中传递名称,例如
.client(get(named("auth")))
【讨论】:
^ 这就是我在当前项目中的做法。 @r2rek 感谢您的回复。你能更清楚地解释我现在如何访问这个模块吗?喜欢var myVariable = NetworkModule.get()
?
基本上你也会有两个你的 Api 接口实例,例如` single("authApi") Retrofit.Builder() .baseUrl(Const.BASE_API_URL) .client(get("auth")) .addConverterFactory(GsonConverterFactory.create(get())) .addCallAdapterFactory(RxJava2CallAdapterFactory.create() ) .build() .create(Api::class.java) `
我明白这一点。我想我的问题并不清楚。我实际上问的是“我现在如何使用这两个 Retrofit 实例”?喜欢这个val api: Api = get("auth")
?
这取决于您将在哪里使用它。如果您将在模块的构造函数中使用它,那么是的,get("auth")
将是要走的路。但是,如果您将直接注入它,那么 inject("auth")
.【参考方案2】:
你可以像下面这样(使用 koin 最新版本的命名属性)。还有为什么我使用 single 和 factory 因为
single——声明给定类型的单例定义。 Koin 只保留此定义的一个实例
factory — 声明给定类型的工厂定义。 Koin 给出了一个新的 每次实例
const val WITH_AUTH: String = "WITH_AUTH"
const val WITH_OUT_AUTH: String = "WITH_OUT_AUTH"
val remoteModule = module
factory(named("HEADERS"))
val map = it.get<MutableMap<String, String>>(0)
Interceptor chain ->
val original = chain.request()
val request = original.newBuilder()
map.forEach entry ->
request.addHeader(entry.key, entry.value)
chain.proceed(request.build())
factory(named("auth"))
OkHttpClient.Builder().apply
map["AUTHORIZATION"] = "token"
readTimeout(1, TimeUnit.MINUTES)
connectTimeout(2, TimeUnit.MINUTES)
writeTimeout(1, TimeUnit.MINUTES)
addInterceptor(get(named("HEADERS"), parameters =
parametersOf(map)
))
.build()
factory(named("auth"))
Retrofit.Builder()
.baseUrl("base_url")
.client(get(named("auth")))
//.addCallAdapterFactory()
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
single(named("noAuth"))
val map = mutableMapOf(ACCEPT to CONTENT_TYPE)
OkHttpClient.Builder().apply
readTimeout(1, TimeUnit.MINUTES)
connectTimeout(2, TimeUnit.MINUTES)
writeTimeout(1, TimeUnit.MINUTES)
addInterceptor(get(named("HEADERS"), parameters =
parametersOf(map)
))
.build()
single(named("noAuth"))
Retrofit.Builder()
.baseUrl("base_url")
.client(get(named("noAuth")))
//.addCallAdapterFactory()
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
现在在您的活动或视图模型中
protected val apiServiceWithoutHeader: ApiService by inject(named(WITH_OUT_HEADER))
protected val apiServiceWithHeader: ApiService by inject(named(WITH_HEADER))
用上述对象调用适当的 API
【讨论】:
我想问这之后的下一步是什么?如何在同一活动中在“noAuth”和“auth”之间切换? @QuanNguyen :我已经更新了我的答案,如果您发现任何问题,请告诉我 a,感谢您提供更新的答案。我应该解释更多。我正在使用 MVVM 架构,有数据源、存储库、视图模型等。在 2 个改造实例旁边的 koin 模块中,我也有 single以上是关于是否可以创建同一对象的不同实例并通过将参数传递给 Koin 中的 get() 函数来访问它们?的主要内容,如果未能解决你的问题,请参考以下文章