Android Koin ans改造中的动态URL
在Android应用程序中使用网络呼叫改造和依赖注入Koin,如何支持动态url更改 (使用应用程序时,用户可以切换到其他服务器) 编辑:网络模块声明如下:Android Koin ans改造中的动态URL,android,dependency-injection,retrofit,koin,Android,Dependency Injection,Retrofit,Koin,在Android应用程序中使用网络呼叫改造和依赖注入Koin,如何支持动态url更改 (使用应用程序时,用户可以切换到其他服务器) 编辑:网络模块声明如下: fun networkModule(baseUrl: String) = module { single<Api> { Retrofit.Builder() .baseUrl(baseUrl) .client(OkHttpClient.
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)
}
我最近也遇到了同样的问题。最方便的方法是使用
拦截器
动态更改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>()))}
要更改url,只需更新拦截器成员
fun baseUrlChanged(baseUrl: String) {
val hostSelectionInterceptor = get<HostSelectionInterceptor>()
hostSelectionInterceptor.host = baseUrl
}
fun baseUrlChanged(baseUrl:String){
val hostSelectionInterceptor=get()
hostSelectionInterceptor.host=baseUrl
}
我尝试过Koin加载/卸载模块。在很短的一段时间内,它工作正常,但后来,经过一次最小的更改后,我无法让它再次重新加载
最后,我用包装器对象解决了这个问题:
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模块中声明如下:
startKoin {
if (BuildConfig.DEBUG) AndroidLogger() else EmptyLogger()
androidContext(this@App)
modules(listOf(networkModule(TEST_API_BASE_URL), storageModule, integrationsModule, appModule))
}
single<DynamicRetrofit>()
{
DynamicRetrofit(get(), get())
}
这是一个很好的解决方案,因为我很少更改baseUrl。如果您需要对两台不同的服务器进行频繁和并行调用,这可能会导致效率低下,因为这样会经常重新创建HTTP客户端。如果不显示您的Koin设置和正在进行的改装,任何人都很难帮到您。您需要为新的基本URL创建一个新的
改型实例。如何将实例改装为需要它的代码取决于需要它的内容以及这些东西本身是如何创建的。当URL发生更改时,您可以使用关闭作用域来强制更新改型实例。您完全正确…我已经包含了代码的相关部分..如果不是作用域,您可以使用URL注释公共接口APIService{@GET Call getUsers(@URL String URL);}重载URL。您好,先生,谢谢您的回复。我对使用koin很陌生。您在哪里声明并使用了“baseUrlChanged(baseUrl:String)”?嘿!在我的例子中,我使用它在不同的测试环境之间进行更改。为此,我的应用程序在导航抽屉中有一个选项,我可以在其中选择所需的后端。在选择时,我调用此函数来设置拦截器中的主机。并且每个新请求都将被更改以使用正确的主机。@woodii您实际上在哪里声明了baseUrlChanged
?看起来像某个作用域函数?放置此函数的最佳位置是可以更改url的位置。你的导航抽屉,调试活动等等。只要确保您可以访问注入的拦截器。
single<DynamicRetrofit>()
{
DynamicRetrofit(get(), get())
}
dynamicRetrofit.api.makeSomeRequest()