Параллельные сопрограммы Kotlin

Допустимо ли сохранять несколько экземпляров задания из отдельных сопрограмм. Предположим, я хочу запустить пару сопрограмм одновременно, в которых они не связаны и не могут произойти в одной сопрограмме, но я хочу, чтобы они выполнялись параллельно. В Android я должен сохранить экземпляр задания, чтобы я мог отменить работу в методе onDestroy. Было бы приемлемо сохранять каждое задание отдельно в списке или я нарушу какое-то правило. Я знаю, что в RX у них есть Подписки, почему нет эквивалента в Kotlin Corouts?

val jobList = arrayListOf<Job>() fun startJob1() { jobList.add(launch { //do some work }) fun startJob1() { jobList.add(launch { //do some other unrelated work }) override fun onDestroy() { super.onDestroy() cancelAllActiveJobs(jobList) } 

Имеет ли этот тип архитектуры смысл для сопрограмм?

Вы можете manullay сохранить список объектов Job которые вы запускаете, но вы также можете использовать родительский-дочерний Job hierarhy, который доступен из коробки, чтобы легче управлять списком запущенных заданий.

Итак, во-первых, вместо списка заданий вы определяете ссылку на родительское задание:

 val job = Job() 

Затем, каждый раз, когда вы начинаете новую сопрограмму, вы делаете ее ребенком этой работы:

 fun startJob1() { launch(job) { // make it a child //do some work } } fun startJob1() { launch(job) { // make it a child //do some other unrelated work } } 

Наконец, когда вам нужно уничтожить свой объект и отменить все задания, вы просто отмените родительское задание.

 override fun onDestroy() { super.onDestroy() job.cancel() } 

Преимущество этого подхода заключается в том, что список рабочих мест управляется автоматически. Новые сопрограммы могут быть запущены и добавлены в родительскую работу, и когда они завершатся, они автоматически удаляются из родительского задания.

Вы можете прочитать больше в соответствующем разделе руководства: https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md#cancellation-via-explicit-job

Это полностью выполнимо, а также ничего особенного. Посмотрите на этот простой пример, который создает 100k заданий сразу:

 val jobs = List(100_000) { // launch a lot of coroutines and list their jobs launch { delay(1000L) print(".") } } jobs.forEach { it.join() } 

Чтобы сделать работу отмененной, она сама должна проверить, была ли она отменена извне, что вы можете сделать с циклом над состоянием активности: while (isActive) .

Вот пример с двумя заданиями, которые затем отменяется:

 fun main(args: Array<String>) = runBlocking { val startTime = System.currentTimeMillis() val jobs = arrayListOf<Job>() jobs += launch { var nextPrintTime = startTime var i = 0 while (isActive) { // check if still active if (System.currentTimeMillis() >= nextPrintTime) { println("Job1: Sleeping ${i++} ...") nextPrintTime += 500L } } } //another job jobs += launch { while (isActive) { // check if still active if (System.currentTimeMillis() >= 42) { println("Job2: Sleeping 42 ...") delay(500L) } } } delay(1300L) // delay a bit println("main: Cancelling the sleeping job!") jobs.forEach { it.cancelAndJoin() } // cancels the job and waits for its completion }