Возможна ли динамическая инъекция зависимостей с помощью Koin

Я исследую Koin библиотеку внедрения зависимостей в моем текущем Android приложении.

У меня есть CoroutineWorker, который завершает всю мою фоновую работу.

Что я хотел бы сделать, так это динамически вводить лямбду для каждого типа фоновой работы, которая у меня есть.

У меня есть следующий код, который работает, но он не динамический

Модуль коин:

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

И мой 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)
    }
}

Могу ли я использовать какой-либо подход, который позволит мне указывать различные лямбда-выражения во время выполнения для внедрения в мой CoroutineWorker?

Например, если в моем модуле lambda Koin было определено 10 лямбд

BackgroundLambdaName_0 - BackgroundLambdaName_9

Затем, когда я начинаю свою уникальную фоновую работу, работаю следующим образом:

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)

person Hector    schedule 29.11.2019    source источник
comment
Да, это возможно, загружая среду выполнения модулей непосредственно перед запуском вашего рабочего и передавая значения динамически для вашего модуля и того же для инъекции.   -  person Jeel Vankhede    schedule 04.12.2019


Ответы (1)


Да, это возможно с Koin 2, по крайней мере, вполне возможно.

Сначала создайте модуль, который вам понадобится, я думаю, это lambdaModule.

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

Затем динамически загружайте модуль и выгружайте его, когда он больше не нужен.

    // after start
loadKoinModules(coffeeAppModule)

// resolve CoffeeMaker
get()<CoffeeMaker>

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

обратитесь к специалисту по сопровождению библиотеки, здесь вы можете найти дополнительные https://medium.com/koin-developers/ready-for-koin-2-0-2722ab59cac3

person PedroAGSantos    schedule 04.12.2019