使用 Koin ans Retrofit 的动态 url
Dynamic urls with Koin ans Retrofit
在Android应用中使用Retrofit进行网络调用和Koin进行依赖注入,如何支持动态url变化?
(在使用应用程序时,用户可以切换到另一个服务器)
编辑:网络模块声明如下:
fun networkModule(baseUrl: String) = module {
single<Api> {
Retrofit.Builder()
.baseUrl(baseUrl)
.client(OkHttpClient.Builder().readTimeout(30, TimeUnit.SECONDS)
.connectTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build())
.build().create(Api::class.java)
}
我在应用程序 class onCreate 中启动 Koin,如下所示:
startKoin {
if (BuildConfig.DEBUG) AndroidLogger() else EmptyLogger()
androidContext(this@App)
modules(listOf(networkModule(TEST_API_BASE_URL), storageModule, integrationsModule, appModule))
}
我最近遇到了同样的问题。最方便的方法是使用 Interceptor
动态更改 baseUrl。
class HostSelectionInterceptor(defaultHost: String? = null, defaultPort: Int? = null) : Interceptor {
@Volatile var host: String? = null
@Volatile var port: Int? = null
init {
host = defaultHost
port = defaultPort
}
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): okhttp3.Response {
var request = chain.request()
this.host?.let {host->
val urlBuilder = request.url().newBuilder()
urlBuilder.host(host)
this.port?.let {
urlBuilder.port(it)
}
request = request.newBuilder().url(urlBuilder.build()).build()
}
return chain.proceed(request)
}
}
使用您的默认 url 初始化它。
single { HostSelectionInterceptor(HttpUrl.parse(AppModuleProperties.baseUrl)?.host()) }
single { createOkHttpClient(interceptors = listOf(get<HostSelectionInterceptor>()))}
并在创建 OkHttpClient
时添加此拦截器。
val builder = OkHttpClient().newBuilder()
interceptors?.forEach { builder.addInterceptor(it) }
要更改 url 您只需更新拦截器成员。
fun baseUrlChanged(baseUrl: String) {
val hostSelectionInterceptor = get<HostSelectionInterceptor>()
hostSelectionInterceptor.host = baseUrl
}
我已经尝试使用 Koin loading/unloading 模块..并且在很短的时间内它起作用了,但是后来,在进行了最小的更改之后我无法再次重新加载它。
最后,我用wrapper对象解决了:
class DynamicRetrofit(private val gson: Gson) {
private fun buildClient() = OkHttpClient.Builder()
.build()
private var baseUrl = "https://etc..." //default url
private fun buildApi() = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(buildClient())
.build().create(MyApi::class.java)
var api: MyApi = buildApi()
private set
fun setUrl(url: String) {
if (baseUrl != url)
baseUrl = url
api = buildApi()
}}
我在 Koin 模块中这样声明它:
single<DynamicRetrofit>()
{
DynamicRetrofit(get(), get())
}
并以非常标准的方式使用它:
dynamicRetrofit.api.makeSomeRequest()
这对我来说是个很好的解决方案,因为我很少更改 baseUrl。如果您需要经常并行调用两个不同的服务器,它可能效率低下,因为您将经常重新创建 HTTP 客户端。
在Android应用中使用Retrofit进行网络调用和Koin进行依赖注入,如何支持动态url变化?
(在使用应用程序时,用户可以切换到另一个服务器)
编辑:网络模块声明如下:
fun networkModule(baseUrl: String) = module {
single<Api> {
Retrofit.Builder()
.baseUrl(baseUrl)
.client(OkHttpClient.Builder().readTimeout(30, TimeUnit.SECONDS)
.connectTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build())
.build().create(Api::class.java)
}
我在应用程序 class onCreate 中启动 Koin,如下所示:
startKoin {
if (BuildConfig.DEBUG) AndroidLogger() else EmptyLogger()
androidContext(this@App)
modules(listOf(networkModule(TEST_API_BASE_URL), storageModule, integrationsModule, appModule))
}
我最近遇到了同样的问题。最方便的方法是使用 Interceptor
动态更改 baseUrl。
class HostSelectionInterceptor(defaultHost: String? = null, defaultPort: Int? = null) : Interceptor {
@Volatile var host: String? = null
@Volatile var port: Int? = null
init {
host = defaultHost
port = defaultPort
}
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): okhttp3.Response {
var request = chain.request()
this.host?.let {host->
val urlBuilder = request.url().newBuilder()
urlBuilder.host(host)
this.port?.let {
urlBuilder.port(it)
}
request = request.newBuilder().url(urlBuilder.build()).build()
}
return chain.proceed(request)
}
}
使用您的默认 url 初始化它。
single { HostSelectionInterceptor(HttpUrl.parse(AppModuleProperties.baseUrl)?.host()) }
single { createOkHttpClient(interceptors = listOf(get<HostSelectionInterceptor>()))}
并在创建 OkHttpClient
时添加此拦截器。
val builder = OkHttpClient().newBuilder()
interceptors?.forEach { builder.addInterceptor(it) }
要更改 url 您只需更新拦截器成员。
fun baseUrlChanged(baseUrl: String) {
val hostSelectionInterceptor = get<HostSelectionInterceptor>()
hostSelectionInterceptor.host = baseUrl
}
我已经尝试使用 Koin loading/unloading 模块..并且在很短的时间内它起作用了,但是后来,在进行了最小的更改之后我无法再次重新加载它。
最后,我用wrapper对象解决了:
class DynamicRetrofit(private val gson: Gson) {
private fun buildClient() = OkHttpClient.Builder()
.build()
private var baseUrl = "https://etc..." //default url
private fun buildApi() = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(buildClient())
.build().create(MyApi::class.java)
var api: MyApi = buildApi()
private set
fun setUrl(url: String) {
if (baseUrl != url)
baseUrl = url
api = buildApi()
}}
我在 Koin 模块中这样声明它:
single<DynamicRetrofit>()
{
DynamicRetrofit(get(), get())
}
并以非常标准的方式使用它:
dynamicRetrofit.api.makeSomeRequest()
这对我来说是个很好的解决方案,因为我很少更改 baseUrl。如果您需要经常并行调用两个不同的服务器,它可能效率低下,因为您将经常重新创建 HTTP 客户端。