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)
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.
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.
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!
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With