Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent Context leak in AsyncTask used by JobService

I need to do some background work which requires a Context in a JobService (I'm using the Firebase JobDispatcher one because we support api 16+) I've read a lot of articles about the JobService and AsyncTasks but I'm unable to find any good articles on how to combine them if you need a Context.

My JobService

import com.firebase.jobdispatcher.JobParameters;
import com.firebase.jobdispatcher.JobService;

public class AsyncJobService extends JobService {

    @Override
    public boolean onStartJob(JobParameters job) {
        new AsyncWork(this, job).execute();
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters job) {
        return false;
    }
}

My AsyncTask

import android.os.AsyncTask;
import com.firebase.jobdispatcher.JobParameters;
import com.firebase.jobdispatcher.JobService;

class AsyncWork extends AsyncTask<Void, Void, Void> {

    private JobService jobService;

    private JobParameters job;

    AsyncWork(JobService jobService, JobParameters job) {
        this.jobService = jobService;
        this.job = job;
    }

    @Override
    protected Void doInBackground(Void... voids) {
        // some work that needs context
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        // some work that needs context
        jobService.jobFinished(job, false);
    }
}

This gives a warning that the jobService property in the AsyncWork class is leaking a context object. I understand why this is the case if you pass an Activity or Fragment but this is a JobService which should exist untill I call jobFinished(). Am I doing something wrong or can I ignore the warning?

like image 573
Sander Avatar asked Nov 08 '22 17:11

Sander


1 Answers

You cannot ignore the warning. Because AsyncWork holds the reference to the Context, the Context cannot be GCed until the task is complete: the Context memory leaks. There are two solutions:

  1. Use a context that is long-lived, anyway, the Application context.
  2. Tie the life of the async task to the life of the context to which it hold a reference: cancel it in onPause
like image 130
G. Blake Meike Avatar answered Nov 14 '22 23:11

G. Blake Meike