Android 在Activity.ondestory()之后更新协同程序中的UI

Android 在Activity.ondestory()之后更新协同程序中的UI,android,kotlin,kotlinx.coroutines,Android,Kotlin,Kotlinx.coroutines,我的活动中包含以下代码: private val job = Job() private val ioScope = CoroutineScope(Dispatchers.IO + job) private val uiScope = CoroutineScope(Dispatchers.Main + job) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)

我的活动中包含以下代码:

private val job = Job()
private val ioScope = CoroutineScope(Dispatchers.IO + job)
private val uiScope = CoroutineScope(Dispatchers.Main + job)

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_second)

    ioScope.launch {
        delay(3000L)
        textView.text = "test1"
        uiScope.launch {
            textView.text = "test2"
        }
    }
}
如果我启动并等待3秒钟,应用程序将崩溃,并出现
调用FromErrorThreadException
,这是可以预测的,因为我从后台线程更新Ui,在
textView.text=“test1”

但若我按下back按钮,我会看到onPause()和onDestroy()将被调用,但后台线程中的
textView.text=“test1”
和UI线程中的
textView.text=“test1”
这两行都将被调用,但毫无例外

为什么它不会崩溃,因为我更新了被破坏活动的UI


这样写代码安全吗?例如,在响应后进行网络调用并更新UI(当活动可能被破坏时),或者可能会出现一些问题?

如果不取消协同路由,基本上就是造成(临时)内存泄漏。在活动被销毁后更新视图实际上不会导致抛出任何异常;相反,这些更改不会反映在任何UI中。您正在更新已丢弃的活动中的值,但由于您的协同程序保留了对该活动的引用,该值仅保留在内存中


正如@Sergey提到的,您应该在
onDestroy()
job.cancel()

不取消协同程序,基本上是造成了(临时)内存泄漏。在活动被销毁后更新视图实际上不会导致抛出任何异常;相反,这些更改不会反映在任何UI中。您正在更新已丢弃的活动中的值,但由于您的协同程序保留了对该活动的引用,该值仅保留在内存中


正如@Sergey提到的,你应该在
onDestroy()
job.cancel()
通常,当活动被破坏时,我们调用
uiScope.cancel()
onDestroy()
中的方法来停止协同程序的作业。@Sergey是的,我看到了,但如果不调用会发生什么?我猜协同程序会继续工作。通常,当活动被销毁时,我们在
onDestroy()
方法中调用
uiScope.cancel()
,以停止协同程序的作业。@Sergey是的,我看到了,但如果不调用会发生什么?我想协同程序将继续工作。我理解正确吗:如果我以这种方式编写代码,将不会出现任何问题,并且在协同程序结束后将释放活动?所以,一般来说,对于短期操作(如internet/数据库请求)启动协同路由而不在存储上取消它是可以接受的?不,您肯定希望在活动被销毁后进行清理。如果不仅仅是内存问题,在活动被销毁后,您还可以在活动中执行一些会导致崩溃的操作,这些问题将很难重现。“在活动被销毁后更新视图实际上不会导致引发任何异常”引用死视图时KotlinNullPointerException如何?除非显式将其设置为null,否则它不会为null。如果它可以为null,那么您必须使用不安全的
视图无论如何都会导致NPE。我是否理解正确:如果我以这种方式编写代码,将不会出现任何问题,并且在协同程序结束后将释放活动?所以,一般来说,对于短期操作(如internet/数据库请求)启动协同路由而不在存储上取消它是可以接受的?不,您肯定希望在活动被销毁后进行清理。如果不仅仅是内存问题,在活动被销毁后,您还可以在活动中执行一些会导致崩溃的操作,这些问题将很难重现。“在活动被销毁后更新视图实际上不会导致引发任何异常”引用死视图时KotlinNullPointerException如何?除非显式将其设置为null,否则它不会为null。如果它可以为null,那么您必须使用不安全的
视图无论如何都会导致NPE。