I have a Service
from which I am starting an AsyncTask
from a given timer to do background tasks. My need requires short bursts of networking tasks so that's why I am sticking with AsyncTask
.
From AsyncTask
, I am doing a number of operations (such as launching notifications) that require Context
. Now, when I am initializing Context
in my AsyncTask
, I am getting a warning "This fields leaks a context object."
I have seen a number of questions regarding the same but they all were related to Activity/Fragment
. So my question is, how can I use Context
in my AsyncTask
(top level class) without leaking it?
I have a Service from which I am starting AsyncTask from a given timer to do background tasks.
Don't use an AsyncTask
. Use a thread. Or, better yet, used ScheduledExecutorService
for the timing component, as that will execute tasks on a background thread. AsyncTask
is only appropriate for when you need to do work on the main application thread when the background part is done, and that's rarely required with a service.
Also, bear in mind that your timer will stop working once your process terminates.
So my question is, how can I use context in my AsyncTask(top level class) without leaking it?
Call getApplicationContext()
on the Service
and use that Context
.
You can pass a WeakReference in your AsyncTask, for example :
public class MyAsynctask extends AsyncTask<Void, Void, Void> {
private WeakReference<Context> mWeakContext;
public MyAsynctask (WeakReference<Context> reference) {
mWeakContext = reference;
}
// when you need context use mWeakContext.get();
}
Hope this helps.
You can try using a WeakReference
and a static inner class for your AsyncTask
to the object you are trying to access.
Something like this:
class MyServiceWhichDoesNotLeak extends Service {
View view;
AsyncTask task;
//Your onCreate and stuff
private static class BackgroundTask extends AsyncTask<Void, Void, String> {
private final WeakReference<View> viewReference;
public BackgroundTask(View view) {
this.viewReference = new WeakReference<>(view);
}
@Override
protected String doInBackground(Void... params) {
// Background stuff
return "something";
}
@Override
protected void onPostExecute(String result) {
View view = viewReference.get();
if (view != null) {
//Use your view
}
}
}
}