Я бы предложил реализовать 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, который учитывает жизненный цикл
person
Willi Mentzel
schedule
17.04.2020