anber
anber

Reputation: 3665

Update UI in coroutine after Activity.onDestroy()

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

Answers (1)

Kevin Coppock
Kevin Coppock

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

Related Questions