Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic urls with Koin ans Retrofit

Using Retrofit for network calls and Koin for dependency injection in an Android app, how to support dynamic url change?

(while using the app, users can switch to another server)

EDIT: network module is declared like this:

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

I am starting Koin in the Aplication class onCreate like this:

 startKoin {

        if (BuildConfig.DEBUG) AndroidLogger() else EmptyLogger()

        androidContext(this@App)

        modules(listOf(networkModule(TEST_API_BASE_URL), storageModule, integrationsModule, appModule))
    }
like image 821
daneejela Avatar asked Sep 18 '25 22:09

daneejela


1 Answers

I faced the same problem recently. The most convenient way is to use a Interceptor to change the baseUrl dynamically.

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

Initialize it with your default url.

single { HostSelectionInterceptor(HttpUrl.parse(AppModuleProperties.baseUrl)?.host()) }
single { createOkHttpClient(interceptors = listOf(get<HostSelectionInterceptor>()))}

And add this interceptor when creating your OkHttpClient.

val builder = OkHttpClient().newBuilder()    
interceptors?.forEach { builder.addInterceptor(it) }

To change the url you only have to update the interceptors member.

fun baseUrlChanged(baseUrl: String) {
    val hostSelectionInterceptor = get<HostSelectionInterceptor>()
    hostSelectionInterceptor.host = baseUrl
}
like image 172
woodii Avatar answered Sep 21 '25 14:09

woodii