Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to create different instances of the same object and access them by passing parameters to get() function in Koin?

I am using Koin as a DI for my app. I created a module:

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

How can I create different HttpClient or Retrofit instances which have different parameters set or has different instantiation? For instance, in some cases, I might need OkHttpClient with AutheniticationInterceptor and in some other cases my client might not need to use it.

Can I pass some parameters when calling get() so that I can get different instances? Any suggestions would be apprieciated.

like image 364
Azizjon Kholmatov Avatar asked Jun 17 '19 11:06

Azizjon Kholmatov


People also ask

Is KOIN a dependency injection?

This article has covered dependency injection and how to use Koin, a Kotlin dependency injection framework, to handle dependencies. Koin has shown to be simple to set up and use.

Does KOIN use reflection?

Koin works without any use of proxies, code generation or reflection. This makes it as usable in Android Apps and Ktor Microservices as standard Java programs.

What is a KOIN component?

Koin is a dependency injection framework for Kotlin. It is lightweight, can be used in Android applications, is implemented via a concise DSL, and takes advantage of Kotlin features like delegate properties rather than relying on annotations.

What is Koin module?

Koin is a smart Kotlin dependency injection library to keep you focused on your app, not on your tools. Koin gives you simple tools and API to let you build, assemble Kotlin related technologies into your application and let you scale your business with easyness. Define Modules. Start Koin. Start on Android.


2 Answers

You can use named properties - e.g.

single<OkHttpClient>(named("auth")){
// here you pass the version with authinterceptor
}
single<OkHttpClient>(named("noAuth")){
// here you pass the version without authinterceptor
}

Then in your get() method you pass the name, e.g.

.client(get(named("auth")))
like image 111
r2rek Avatar answered Sep 18 '22 14:09

r2rek


You can do like below (Use koin latest version for named property).Also why I use single and factory because

single— declare a singleton definition of given type. Koin keeps only one instance of this definition

factory — declare a factory definition of given type. Koin gives a new instance each time

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

Now in your activity or viewModel

protected val apiServiceWithoutHeader: ApiService by inject(named(WITH_OUT_HEADER))
protected val apiServiceWithHeader: ApiService by inject(named(WITH_HEADER))

with above object call appropriate API

like image 27
Shweta Chauhan Avatar answered Sep 19 '22 14:09

Shweta Chauhan