Я бы предложил реализовать getInfo
как функцию приостановки, которая знает контекст, в котором она должна выполняться. Таким образом, не имеет значения, из какого контекста вы его вызываете (*).
Кроме того, я бы не использовал обратные вызовы для продолжения работы. Вы можете просто выбрать из того, что getInfo()
возвращает, как действовать (**).
Это на самом деле самое большое в сопрограммах, вы можете превратить код на основе обратного вызова в код, который читается как последовательный код.
Так как вам не нужны результаты getOne()
и getTwo()
, использование launch
является правильным способом. Возвращает Job
. Вы можете приостановить сопрограмму, пока обе функции не будут завершены с joinAll()
, который может быть вызван на Collection<Job>
.
suspend fun getInfo() = withContext(Dispatchers.IO) {
try {
listOf(
launch { getOne() },
launch { getTwo() }
).joinAll()
false
} catch (e: Throwable) {
true
}
}
Вам не нужно использовать GlobalScope
, просто создайте свою собственную (** *).
Я использовал Default
в качестве контекста для запуска getInfo
, но любой другой контекст тоже подойдет, так как getInfo
будет работать на том, который должен.
val newScope = CoroutineScope(Dispatchers.Default).launch {
val error = getInfo()
if(error) {
onSuccess()
} else {
onError()
}
}
// "newScope" can be cancelled any time
* В случае, если я использовал Dispatcher.IO
, чтобы представить, что две функции выполняют какую-то длительную работу ввода-вывода.
** Я использовал простой здесь логическое значение, но, конечно, вы можете вернуть что-то более значимое.
*** или подключитесь к некоторой области, заданной средой Sourrouding, учитывающей жизненный цикл