Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Dynamic Dependency Injection with Koin possible

Tags:

android

koin

I am investigating Koin dependency injection library in my current Android application.

I have a CoroutineWorker that completes all my background work.

What I would like to do is Dynamically inject a lambda for each type of background work I have.

I have the following code that works, however it is not Dynamic

Koin Module:

const val BackgroundLambdaName: String = "back-ground-lambda"

val lambdaModule = module {

    single(qualifier = named(BackgroundLambdaName)) {
        background
    }
}

private val background: suspend CoroutineScope.(Service) -> Unit = { service: Service ->
    val limit: Int = 200
    var offset: Int = 0

    loop@ while (true) {

        val networkResponse = service.move(options = mutableMapOf("limit" to limit, "offset" to offset))

        if (networkResponse.next == null) {
            break@loop
        }
        offset += limit
    }
}

And my CoroutineWorker:

class BackgroundWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params), KoinComponent {

    private val service: Service by inject()
    private val x_background: suspend CoroutineScope.(Service) -> Unit by inject(qualifier = named(BackgroundLambdaName))

    override suspend fun doWork(): Result = coroutineScope {

        withContext(Dispatchers.IO) {
            downloadSynchronously(this)
            Result.success()
        }
    }

    private suspend fun downloadSynchronously(coroutineScope: CoroutineScope) {
        x_background(coroutineScope, service)
    }
}

Is there any approach I can take that will allow me to specify different lambdas at runtime to inject into my CoroutineWorker?

For example if my lambda Koin module had 10 lambdas defined

BackgroundLambdaName_0 - BackgroundLambdaName_9

Then when starting my unique background work as follows:

val constraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .setRequiresBatteryNotLow(true)
    .setRequiresCharging(true)
    .build()

val backgroundWorkRequest = OneTimeWorkRequestBuilder<BackgroundWorker>()
    .setConstraints(constraints)
    .setBackoffCriteria(
        BackoffPolicy.EXPONENTIAL,
        OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
        TimeUnit.MILLISECONDS
    ).build()

// DYNAMICALLY set qualifier = named(BackgroundLambdaName) to one of 
// BackgroundLambdaName_0 - BackgroundLambdaName_9

WorkManager.getInstance(application).enqueueUniqueWork(UNIQUE_WORK_NAME, ExistingWorkPolicy.KEEP, backgroundWorkRequest)
like image 300
Hector Avatar asked Nov 29 '19 13:11

Hector


People also ask

Is KOIN a dependency injection?

This lightweight framework provides its dependency injection capabilities through a DSL, which is hard to achieve in Java-dedicated Guice. Apart from being an expressive way to declare dependencies between entities in our code, Koin natively supports popular Kotlin applications, such as Ktor and the Android platform.

Is KOIN better than dagger?

As I mentioned before Dagger/Hilt has a significant impact on build time due to code generation. On the other hand, Koin also affects time, but not build, but runtime. Koin has slightly worse runtime performance, because it resolves dependencies at runtime.

Does KOIN use reflection?

Koin as per official docs , is A pragmatic lightweight dependency injection framework for Kotlin developers. Written in pure Kotlin using functional resolution only: no proxy, no code generation, no reflection!


1 Answers

Yes it is possible with Koin 2 at least is totally possible.

First create module that would be needed I guess for you is 'lambdaModule'

val coffeeAppModule = module {
    single { CoffeeMaker(get(), get()) }
    single<Pump> { Thermosiphon(get()) }
    single<Heater> { ElectricHeater() }
}

Then dynamically load the module and unload when you don't need anymore.

    // after start
loadKoinModules(coffeeAppModule)

// resolve CoffeeMaker
get()<CoffeeMaker>

// drop module's definitions & instances when you don't need it anymore
unloadKoinModules(coffeeAppModule)

please refer to maintainer of the library here you can find more https://medium.com/koin-developers/ready-for-koin-2-0-2722ab59cac3

like image 94
PedroAGSantos Avatar answered Sep 29 '22 12:09

PedroAGSantos