android withContext未执行

e5njpo68  于 2023-05-12  发布在  Android
关注(0)|答案(2)|浏览(146)

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)
        }

有人能解释一下为什么会这样吗?

zkure5ic

zkure5ic1#

确保withContext(Dispatchers.Main)之前的代码不会出错/抛出异常,因为您正在打开一个IO线程,这些代码会被忽略,但它们后面的代码不会被执行。

jchrr9hc

jchrr9hc2#

您使用的是生命周期作用域,因此如果启动的Activity超出作用域,则会取消协程。但是,被取消的协程将继续运行,直到它支持取消的下一个点。从标准协程库(如withContext())调用suspend函数是支持取消的一种方法。
例如,当用户旋转屏幕时,如果您的协程在inputStream.close()行附近运行,则生命周期结束,协程被取消,但它将继续执行该行下的所有代码,直到它到达下一个suspend函数,即withContext()。然后,它最终可以停止执行,您的startActivity函数将永远不会到达。
这就是为什么如果从withContext块中取出startActivity函数,它仍然会被调用。这不是好事!您的协程应该支持提示取消以避免内存泄漏。从主线程调用startActivity也是不安全的。结果可能会出现运行时异常。
从总体上看,这段代码应该被移到ViewModel中,这样如果在加载图像的同时屏幕旋转,这个过程就不会丢失。

相关问题