Reputation: 1225
In the MainActivity, every x seconds I create a new AsyncTask and I call execute with new RTask(this).execute(param);
to send data to a server asyncronously. I think that create a new task so often can cause memory leaks. So when garbage collector release the memory and how can I set the task reference to null to allow to collect it?
I've tried to use this.cancel(true);
within onPostExecute()
but I've read that, due to a bug of the Android framework, onpost is never called. Any suggestion will be greatly appreciated.
Thanks
Upvotes: 1
Views: 3949
Reputation: 11185
How garbage collector release AsyncTask allocated memory
Like it releases memory for any other class. There is nothing special about an AsyncTask. Once the task is done it will be garbage collected as long as no other class refers to it. Setting the task reference to null will help.
Upvotes: 1
Reputation: 12643
Actually, there shouldn't be any issue with AsyncTask
recycling unless You hold any reference to it from param
or generate memory leaks inside doInBackground()
.
So, You might think, that if You're creating many long-running AsyncTasks then it would lead to some memory issues. Actually it's not true (at least on latest Android versions). AsyncTask
source code shows that
It uses singleton bounded executor:
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 1;
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
That means that executor won't run more than 128 AsyncTasks the same time (128 is not very big per my understanding).
It uses bounded query for the Executor:
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(10);
So, based on the above points, number of created and running the same time AsyncTasks
are limited and not so big. So, if Your code inside AsyncTask
doesn't create any memory leaks, then per my understanding there's no issue. Same time Android won't let You spam itself with AsyncTasks
. Checkout ThreadPoolExecutors description to get familiar with the way it manages a memory (If You worry about too many created threads the same time).
Especially in Your case, I don't think that it's a good idea to execute another request to the server while previous one is not finished yet (in case of similar requests), also there's no point to execute many frequent small requests - Your app will draw battery too fast in this case.
Regarding cancel()
call, based on Android documentation for AsyncTask:
Cancelling a task
A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns. To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)
So, I'm not sure that You've meant by "I've tried to use this.cancel(true); within onPostExecute()" while cancel()
has nothing to do if called from onPostExecute()
. It can be called out from AsyncTask
or from doInBackground()
and it's a good practice to call isCancelled() if You have a loop in AsyncTask
in order to stop its execution once cancel()
called.
Upvotes: 5