getsadzeg
getsadzeg

Reputation: 660

Why can't Android release the finished activity from memory after AsyncTask finishes?

So I read about memory leaks in Android regarding AsyncTask, and in essence, as far as I understood it's when activity is destroyed for some reason but AsyncTask isn't done, so because AsyncTask has a strong reference to Activity, GC can't collect Activity, i.e. can't release it from memory. My question is, if/when AsyncTask finishes its work and is no longer needed, why can't GC collect that referenced Activity then? Why would that be a problem?

Upvotes: 0

Views: 155

Answers (1)

Taseer
Taseer

Reputation: 3502

Generally, inner classes often outlive their parents which is why the parent class become not eligible for GC. As for AsyncTask, if make your async task inner and provide it with a context of your activity, Android studio will warn that it might cause memory leaks.

This AsyncTask class should be static or leaks might occur (anonymous android.os.AsyncTask) A static field will leak contexts. Non-static inner classes have an implicit reference to their outer class. If that outer class is, for example, a Fragment or Activity, then this reference means that the long-running handler/loader/task will hold a reference to the activity which prevents it from getting garbage collected. Similarly, direct field references to activities and fragments from these long-running instances can cause leaks. ViewModel classes should never point to Views or non-application Contexts.

Non-static inner class outlives its parent. But when you don`t declare it inner that means that you do not have access to parent class members anymore. You can pass in a reference to the Context of your activity but then you run the same risk of a memory leak.

Solution?

A possible solution is to provide a weak reference to your context. Another solution is to cancel your async task in onStop() callback of your activity. Moreover, you can confirm the state of your activity using activityContext.isFinishing(). If the state equals true, simply cancel or return your async task.

A little off topic. Async tasks are a thing of the past, there are other better methods to handle concurrency like RxJava, Kotlin`s coroutines and etc.

Upvotes: 1

Related Questions