I initialize a member variable in my Activity class
private String test = new String("A");
then I use it to write to Log in a long time consuming loop in doInBackground()
method of an anonymous AsyncTask launched from the Activity
new AsyncTask<Void, Void, Void>() {
@Override
protected void onPreExecute() {
}
@Override
protected void onPostExecute(Void result) {
}
@Override
protected Void doInBackground(Void... params) {
for (int j = 10; j >= 0; j--) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i("DOINBACKGROUND ", test);
}
}.execute();
QUESTION:
When I leave Activity while Asynctask
is still executing, and after Activity's onDestroy()
is executed, I see in the Log that the member variable is still alive and not destroyed. Can someone explain to me how is it possible?
BOUNTY QUESTION:
the member variable is still alive because, even after onDestroy()
, it isnt yet garbaged due to gc criteria and gc priority. This is ok.
But my doubt is if
doInBackground()
always and surely without crashing (although with a temporary memory consumption)or instead
If you start an AsyncTask inside an Activity and you rotate the device, the Activity will be destroyed and a new instance will be created. But the AsyncTask will not die. It will go on living until it completes.
In summary, the three most common issues with AsyncTask are: Memory leaks. Cancellation of background work. Computational cost.
AsyncTask instances can only be used one time.
AsyncTask class is firstly executed using execute() method. In the first step AsyncTask is called onPreExecute() then onPreExecute() calls doInBackground() for background processes and then doInBackground() calls onPostExecute() method to update the UI.
Don't confuse garbage collection and the activity lifecycle.
An object can be garbage collected once all references traceable to it from GC root objects are gone.
onDestroy()
is part of the activity lifecycle. Essentially the framework is done with the activity and is giving up any references it might have been holding to the activity and related resources.
When you instantiate an anonymous inner class, it gets an implicit reference to the parent object. To put it in another way, an anon inner class is always a non-static inner class. This parent reference is a reference to your Activity
. You're then passing the async task object to an executor with a call to execute()
and the executor holds the async task reference as long as it is needed, also preventing the referenced activity from being garbage collected.
Thus the asynctask in my snippet example will complete its doInBackground() always and surely without crashing due to NPE?
Yes. But do consider the following:
Make your inner classes static
unless they specifically need to access the parent object. Since anon inner classes are always non-static
, make them non-anonymous.
Mixing async operations in objects with separate lifecycle (such as activities or fragments) is fragile and it is better avoided. Problems include e.g. cancellation, results delivery to a gone object, and keeping GC-preventing references to expensive objects such as activities.
First of all, onDestroy() happens just before destroying the activity and asks the activity manager to release all the resources tied to that activity. It means that all the activity's resources will be candidate for being removed by gc. However, it doesn't force the gc to remove the resources from the memory, they are just candidates. These candidate will be scored by the gc based on their size, age, recency, type and etc and whenever the system needs more space, it asks gc to remove candidates and it does it based on their scores. The candidate with a higher score is most likely to be deleted first.
This is noticeable when you see a crash out of nowhere, even after you quit from your application.
You might be able to see this crash if you create another activity and call System.gc() on it.
Cheers A.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With