Мне было интересно, какое объявление будет правильным для длительной задачи.
suspend fun methodName(image: Bitmap?): String? = async {
// heavy task
}.await()
ИЛИ ЖЕ
fun methodName(image: Bitmap?): String? {
//heavyTask
}
И в коде использовать
async{
methodName()
}.await()
Первый ограничивает выполнение тяжелых операций в фоновом потоке всегда. Итак, это безопасно (в том смысле, что он будет запускаться в фоновом потоке, так что новые разработчики обязательно будут использовать его в приостановленной конструкции).
Какой подход лучше?
Рассмотрите возможность использования withContext() вместо async{}.await() в вашем случае.
Что касается вашего вопроса, ИМХО, лучше использовать такую конструкцию:
suspend fun methodName(image: Bitmap?): String? = withContext(CommonPool) {
// heavy task
}
@ Viking93 зависит от того, что вы пытаетесь сделать. Если вы создаете общедоступный API библиотеки, лучше делегировать работу с потоками разработчику, потому что вы не должны заставлять других разработчиков использовать Kotlin, сопрограммы и т. д. В противном случае, если этот код будет использоваться только в вашей команде, мой пример - это то, что вам нужно, потому что он использует ваш стек технологий и помогает избежать возможных проблем с потоками (вы можете указать контекст сопрограммы только один раз).
Я считаю, что ключевое слово suspend является серьезным предупреждением для пользователя, чтобы предотвратить использование определенной функции в конфиденциальных потоках. Но так бывает не всегда. как сказано в документация сопрограмм:
the library can decide to proceed without suspension, if the result for the call in question is already available
Если «тяжелая задача» должна быть простой. (пример: копирование файла) Лично я просто добавляю приостановку функции без создания сопрограммы. Пользователь сам отвечает за то, где будет вызвана эта функция.
@Throws(IOException::class)
suspend fun copy(input: File, output: File) {
//copying
}
Если «тяжелая задача» состоит из других функций suspend. Предупреждение - это обычно couroutineContext в параметре функции. А внутри он использует такие функции, как withContext().
withContext : suspends until it completes, and returns the result
@Throws(IOException::class)
suspend fun copyMultiple(context: CoroutineContext, pairFiles: List<Pair<File, File>>) {
pairFiles.forEach { (input, output) ->
withContext(context) {
copy(input, output)
}
}
}
Вопрос в том, должен ли я отдавать контроль «выполнять тяжелую задачу, не зависящую от пользовательского интерфейса, в любом потоке, разработчику» или я не должен.