startActivity(..)没有从withContext块中调用,并且delay也没有被调用。
如果我将startActivity(..)移出withContext块,则会调用它。
var image: Bitmap? = null
lifecycleCoroutineScope.launch(Dispatchers.IO) {
val conn = URL(content.image).openConnection()
conn.connect()
val inputStream = conn.getInputStream()
image = BitmapFactory.decodeStream(inputStream)
inputStream.close()
val file = image?.let {
saveFile(it, "file")
}
file?.let {
intent.putExtra(
Intent.EXTRA_STREAM, FileProvider.getUriForFile(
context,
environmentProvider.fileProviderAuthority,
it
)
)
}
withContext(Dispatchers.Main) {
startActivity(context, intent, null)
}
delay(1000)
}
有人能解释一下为什么会这样吗?
2条答案
按热度按时间zkure5ic1#
确保
withContext(Dispatchers.Main)
之前的代码不会出错/抛出异常,因为您正在打开一个IO线程,这些代码会被忽略,但它们后面的代码不会被执行。jchrr9hc2#
您使用的是生命周期作用域,因此如果启动的Activity超出作用域,则会取消协程。但是,被取消的协程将继续运行,直到它支持取消的下一个点。从标准协程库(如
withContext()
)调用suspend函数是支持取消的一种方法。例如,当用户旋转屏幕时,如果您的协程在
inputStream.close()
行附近运行,则生命周期结束,协程被取消,但它将继续执行该行下的所有代码,直到它到达下一个suspend函数,即withContext()
。然后,它最终可以停止执行,您的startActivity
函数将永远不会到达。这就是为什么如果从
withContext
块中取出startActivity
函数,它仍然会被调用。这不是好事!您的协程应该支持提示取消以避免内存泄漏。从主线程调用startActivity
也是不安全的。结果可能会出现运行时异常。从总体上看,这段代码应该被移到ViewModel中,这样如果在加载图像的同时屏幕旋转,这个过程就不会丢失。