android - Inappropriate blocking method call, but Suspend function 'withContext' should be called only from a coroutine or another suspend function
问题描述
In my Service, I need to call on onStartCommand
some methods that require withContext(Dispatchers.IO)
instead CoroutineScope(Dispatchers.IO)
like:
- url = URL(pokemon.linkImage)
- url.openConnection().getInputStream()
- fOut= FileOutputStream(file)
- fOut.flush()
- fOut.close()
But Suspend function 'withContext' should be called only from a coroutine or another suspend function
. So if onStartCommand
can't be a suspend function because it has override and withContext
can't be called by CoroutineScope because Inappropriate blocking method call
of methods
val url = URL(pokemon.linkImage)
val iS = url.openConnection().getInputStream()
How can I resolve this problem?
My onStartCommand():
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
//create the directory on internal storage that will contains all pokemon images
val path = applicationContext.filesDir.absolutePath
val dirName = "/pokeimg"
val dir = File(path, dirName)
if(!dir.exists())
dir.mkdir()
CoroutineScope(Dispatchers.IO).launch {
//get the list of pokemon when they are loaded from repository
val listOfPokemon =
PersistenceSingletonRepository.getInstance(applicationContext).getListOfPokemon()
//download all the image for each pokemon in the list, but only if the image is
//not present in the directory
for(pokemon in listOfPokemon) {
val imageName = "${pokemon.name}.png"
val file = File("${dir.absolutePath}/$imageName")
//check if image not exists on internal storage and if is not an official-artwork
//images that aren't official-artwork has less quality so don't resize
if(!file.exists()) {
//download img
val url = URL(pokemon.linkImage)
val iS = url.openConnection().getInputStream()
val opts = BitmapFactory.Options()
if (!Utils.isBadImage(pokemon.linkImage)) {
//request a smaller image
opts.inSampleSize = 2
}
val bitmap = BitmapFactory.decodeStream(iS, null, opts)
val fOut= FileOutputStream(file)
bitmap?.compress(Bitmap.CompressFormat.PNG, 100, fOut)
fOut.flush()
fOut.close()
}
}
stopSelf()
}
return START_NOT_STICKY
}
解决方案
您可以放心地忽略该警告,已知它有很多误报。您在 IO 调度程序中启动了协程,该调度程序是为阻塞调用而设计的。
另一方面,使用CoroutineScope
没有父节点和生命周期绑定的 ad-hoc 启动任何东西通常是错误的做法。您应该尊重服务生命周期并在onDestroy
. 例如,请参见此处。
推荐阅读
- selenium - Selenium-wire 响应对象 - 将响应主体作为字符串而不是字节获取的方法
- java - 我想通过蓝牙将数据从 Android 发送到 Arduino
- javascript - 通过添加 cookie 进行 CSS 样式表切换
- r - 如何解决 UseMethod() 中的此错误?
- qt - Qt/QML - 如何自定义 Popup 调光效果?
- java - org.jasypt.exceptions.EncryptionOperationNotPossibleException 抛出 HTTP 状态 500
- kotlin - 无法构建/运行 Jetpack Compose Multiplatform 的桌面版本,即使在最新版本的 IntelliJ 上的全新项目上也是如此
- java - 如何从代码的另一部分中的公共 ClassName 访问数据?
- javascript - WkWebview javascript动画在屏幕锁定时冻结
- pine-script - 我可以在同一个脚本中使用 overlay = true 和 overlay = false 吗?