正确使用 CoroutineScope 和 retrofit api 调用
Correct use CoroutineScope with retrofit api call
这是正确的协程和改造使用吗?
我在服务拦截方面遇到了一些问题(通过拦截获取 getAccessTokenBlocking 时出现 RuntimeException),可能是由于 CoroutineScope 使用不正确?
override fun onBindViewHolder(...){
val service = serviceBuilderFactory
.create(serviceEndpoint, acc)
.buildWithCache(Service::class.java)
CoroutineScope(Dispatchers.IO)
.launch(exceptionHandler) {
val obj = service.getObj()
//should i use here for webView.post - withContext(Dispatchers.Main) { ??????
// or shoud i use async and resume webView.post after callback?
webView.post {
webView.loadUrl(obj.url)
}
}
}
改造
@GET("/url")
suspend fun getObj(): Obj
这根本不应该在适配器中。每次项目滚动到屏幕上时,您都会触发协程,并且由于您创建了一个 one-off CoroutineScope 来启动每个协程,因此您无法取消它们。如果用户快速旋转屏幕几次,您将在后台拥有大约 30 个您无法取消的过时协同程序 运行,其中许多将执行冗余工作。
相反,您应该在 ViewModel 中进行提取,这样在屏幕旋转时不必重复提取。并使用 viewModelScope
启动协程,以便当它们从当前屏幕超出范围时变得过时时自动取消。
如果您不介意 pre-fetching 每个项目的数据在 RecyclerView 中显示之前,您可以映射您的数据类型以包含获取的 URL,然后再将其公开给您的 Activity/Fragment 通过 LiveData 或 Flow。
如果您只想在项目出现在屏幕上时才延迟加载 URL,您可以使用 async(start = CoroutineStart.LAZY) { ... }
将您的数据类型映射到 Deferred<String>
。然后将 CoroutineScope 参数添加到适配器的构造函数,以便 Activity 可以传递 lifecycleScope
或 Fragment 可以传递 viewLifecycleScope
,并且您可以使用该范围在适配器中启动协程,协程将自动取消过时的时候。您可以使用这些协程 await()
延迟的 URL.
这是正确的协程和改造使用吗? 我在服务拦截方面遇到了一些问题(通过拦截获取 getAccessTokenBlocking 时出现 RuntimeException),可能是由于 CoroutineScope 使用不正确?
override fun onBindViewHolder(...){
val service = serviceBuilderFactory
.create(serviceEndpoint, acc)
.buildWithCache(Service::class.java)
CoroutineScope(Dispatchers.IO)
.launch(exceptionHandler) {
val obj = service.getObj()
//should i use here for webView.post - withContext(Dispatchers.Main) { ??????
// or shoud i use async and resume webView.post after callback?
webView.post {
webView.loadUrl(obj.url)
}
}
}
改造
@GET("/url")
suspend fun getObj(): Obj
这根本不应该在适配器中。每次项目滚动到屏幕上时,您都会触发协程,并且由于您创建了一个 one-off CoroutineScope 来启动每个协程,因此您无法取消它们。如果用户快速旋转屏幕几次,您将在后台拥有大约 30 个您无法取消的过时协同程序 运行,其中许多将执行冗余工作。
相反,您应该在 ViewModel 中进行提取,这样在屏幕旋转时不必重复提取。并使用 viewModelScope
启动协程,以便当它们从当前屏幕超出范围时变得过时时自动取消。
如果您不介意 pre-fetching 每个项目的数据在 RecyclerView 中显示之前,您可以映射您的数据类型以包含获取的 URL,然后再将其公开给您的 Activity/Fragment 通过 LiveData 或 Flow。
如果您只想在项目出现在屏幕上时才延迟加载 URL,您可以使用 async(start = CoroutineStart.LAZY) { ... }
将您的数据类型映射到 Deferred<String>
。然后将 CoroutineScope 参数添加到适配器的构造函数,以便 Activity 可以传递 lifecycleScope
或 Fragment 可以传递 viewLifecycleScope
,并且您可以使用该范围在适配器中启动协程,协程将自动取消过时的时候。您可以使用这些协程 await()
延迟的 URL.