Это блокирует поток пользовательского интерфейса, но если я использую GlobalScope, пользовательский интерфейс не будет заблокирован.
lifecycleScope.launch {
activity?.runOnUiThread {
Toast.makeText(activity, getString(R.string.txt_savinginprogress), Toast.LENGTH_SHORT).show()
}
val fileName = "Picture" + System.currentTimeMillis().toString()
val folderName = "BucketList"
val bitmap: Bitmap? = photoURI?.let { it1 -> getBitmapFromUri(it1) }
activity?.let {
bitmap?.let { it1 ->
PhotoSaveHelper(it).savePhoto(fileName, folderName, it1)
}
}
activity?.runOnUiThread {
Toast.makeText(activity, getString(R.string.txt_saved), Toast.LENGTH_SHORT).show()
}
}
}
Спасибо, моя проблема решена: lifecycleScope.launch { withContext(Dispatchers.IO) { ... }}
Да, это способ правильно использовать его. И вообще не нужно runOnUiThread
. Просто держите эти части кода вне блоков withContext
.
lifecycleScope.launch{}
по умолчанию выполняет код внутри потока main
.
Попробуйте использовать приведенный ниже код для запуска сопрограммы в диспетчере ввода-вывода (для длительных и ресурсоемких задач).
lifecycleScope.launch(Dispatchers.IO) {
withContext(Dispatchers.Main) {
Toast.makeText(activity, getString(R.string.txt_savinginprogress), Toast.LENGTH_SHORT).show()
}
}
Это наизнанку. Диспетчер верхнего уровня должен оставаться как есть (Main
) и в withContext(IO)
должна идти только работа по блокировке
Приводит ли их обмен к проблемам с производительностью или это противоречит лучшим практикам?
Есть некоторые теоретические проблемы с производительностью, такие как передача в поток ввода-вывода только для немедленной передачи обратно в поток пользовательского интерфейса, но это не так важно. Это просто делает код более уродливым и трудным для понимания, когда вы делаете это таким образом. OTOH, это зависит от варианта использования, если у вас много вызовов ввода-вывода и только один доступ к пользовательскому интерфейсу в середине, этот способ может привести к лучшему коду.
Lifecyclescope по умолчанию использует диспетчер основного потока.