RunBlocking 与 Dispatcher 通信不起作用
RunBlocking with Dispatcher communication not working
I have switched my context to Dispatcher.Main to show UI but data fetched on runBlocking but unable to display in RecylerView
runBlocking {
var fruits = fetchFruitList()
withContext(Dispatchers.Main){
recyclerView.adapter = FruitAdapter(fruits);
}
}
我做错了什么以及return数据从一个 Dispatcher 到另一个 Dispatcher 的正确方法是什么。
我试过另一种方法
GlobalScope.launch {
withContext(Dispatchers.IO){
var fruits = arrayOf("Grapes","Apple","Mango","TuttiFruit","PineApple",
"Pomegrante","Apple","Mango","TuttiFruit","PineApple",
"Pomegrante","Apple","Mango","TuttiFruit","PineApple").toList()
return@withContext
}
recyclerView.adapter = FruitAdapter(fruits)
}
但以上述方式 I have to declare fruits as global
而我不想让它在全球范围内工作。有没有办法 return 数据从一个 '调度程序队列到另一个
I have to fetch data from Api (IO operation) and display that data in RecyclerView(Main Thread Operation)
那是因为你必须在获取数据后切换上下文:
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
查看文档第一段。
Runs a new coroutine and blocks the current thread interruptibly until
its completion. This function should not be used from a coroutine. It
is designed to bridge regular blocking code to libraries that are
written in suspending style, to be used in main functions and in
tests.
其次,您要求GlobalScope
用法。是的,如果你在 Android 中执行协程,你应该避免这种情况。 Reasons here.
如何在AndroidActivity/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()
}
关于你的问题:
what am I doing wrong and what is the appropriate way to return data
from one Dispatcher to another
如果您想 return 来自不同上下文的值,您也可以尝试此解决方案:
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
}
}
I have switched my context to Dispatcher.Main to show UI but data fetched on runBlocking but unable to display in RecylerView
runBlocking {
var fruits = fetchFruitList()
withContext(Dispatchers.Main){
recyclerView.adapter = FruitAdapter(fruits);
}
}
我做错了什么以及return数据从一个 Dispatcher 到另一个 Dispatcher 的正确方法是什么。
我试过另一种方法
GlobalScope.launch {
withContext(Dispatchers.IO){
var fruits = arrayOf("Grapes","Apple","Mango","TuttiFruit","PineApple",
"Pomegrante","Apple","Mango","TuttiFruit","PineApple",
"Pomegrante","Apple","Mango","TuttiFruit","PineApple").toList()
return@withContext
}
recyclerView.adapter = FruitAdapter(fruits)
}
但以上述方式 I have to declare fruits as global
而我不想让它在全球范围内工作。有没有办法 return 数据从一个 '调度程序队列到另一个
I have to fetch data from Api (IO operation) and display that data in RecyclerView(Main Thread Operation)
那是因为你必须在获取数据后切换上下文:
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
查看文档第一段。
Runs a new coroutine and blocks the current thread interruptibly until its completion. This function should not be used from a coroutine. It is designed to bridge regular blocking code to libraries that are written in suspending style, to be used in main functions and in tests.
其次,您要求GlobalScope
用法。是的,如果你在 Android 中执行协程,你应该避免这种情况。 Reasons here.
如何在AndroidActivity/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()
}
关于你的问题:
what am I doing wrong and what is the appropriate way to return data from one Dispatcher to another
如果您想 return 来自不同上下文的值,您也可以尝试此解决方案:
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
}
}