Это потому, что вы должны переключать контекст после получения данных:
GlobalScope.launch(Dispatchers.IO){
var fruits = arrayOf("Grapes","Apple","Mango","TuttiFruit","PineApple",
"Pomegrante","Apple","Mango","TuttiFruit","PineApple",
"Pomegrante","Apple","Mango","TuttiFruit","PineApple").toList()
withContext(Dispatchers.MAIN){
recyclerView.adapter = FruitAdapter(fruits)
}
}
Редактировать Согласно комментариям:
Для runBlocking
ознакомьтесь с первым абзацем документации.
Запускает новую сопрограмму и прерывает текущий поток до его завершения. Эта функция не должна использоваться из сопрограммы. Он предназначен для связывания регулярного кода блокировки с библиотеками, написанными в стиле приостановки, для использования в основных функциях и в тестах.
Во-вторых, вы запрашиваете использование GlobalScope
. Да, если вы делаете сопрограммы в Android, вам следует избегать этого. Причины здесь .
Как запустить сопрограмму в Android Activity / Fragment?
Сначала я предлагаю использовать в ViewModel
или Presenter
, но если вы хотите запустить сопрограмму в Activity / Fragment, вам понадобится способ контролировать и управлять ее отменой, чтобы избежать утечки памяти,Решение для этого будет:
private val job: Job = Job()
//or Dispatchers.IO
private val fragmentScope = CoroutineScope(Dispatchers.MAIN + job)
//launch a coroutine later in Activity/Fragment
fragmentScope.launch{
//the default coroutine dispatcher would be the defined dispatcher above
}
override fun onDestroy(){
super.onDestroy()
fragmentScope.cancel()
}
Что касается вашего вопроса:
что я делаю не так и как правильно вернуть данные из одного диспетчера в другой
Вы также можете попробовать это решение, если хотите вернуть значения из другого контекста:
someScope.launch(Dispatchers.MAIN){
var data = withContext(Dispatchers.IO){
val someData = fetchSomeData()
return@withContext data
}
if(data.isAvailable()){ //for example
//runing on the main thread
}
}