Reputation: 3665
I have this code in my activity:
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"
}
}
}
If I launch and wait 3 seconds app will crash with CalledFromWrongThreadException
which is predictable cause I update Ui from background thread in line textView.text = "test1"
.
But if I press back button I see that onPause() and onDestroy() will be called, but both lines textView.text = "test1"
in background thread and textView.text = "test1"
in UI thread will be called, but without exception.
Why it does not crash, cause I update UI on destroyed activity?
Is it safe to write code in such way? For example, do a network call and update UI after response(when Activity could be destroyed), or there could be some issues?
Upvotes: 2
Views: 1726
Reputation: 134684
You're basically causing a (temporary) memory leak by not cancelling the coroutine. Updating a View after the Activity is destroyed will not actually cause any exception to be thrown; rather, the changes just won't be reflected in any UI. You're updating values in an Activity that has been discarded, but only kept in memory due to your coroutine keeping a reference to it.
As @Sergey mentions, you should job.cancel()
in onDestroy()
.
Upvotes: 4