package org.commcare.tasks.templates; import android.os.AsyncTask; import android.os.Build; import java.util.ArrayList; /** * AsyncTask that is registered, enabling the task to be cancelled if the * session ends. Useful since the session ending might close resources that the * task depends on to proceed. * * @author Phillip Mates (pmates@dimagi.com) */ public abstract class ManagedAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> { /** * List of running tasks. Tasks add/remove themselves automatically upon * start, cancellation, and completion. */ private static final ArrayList<ManagedAsyncTask<?, ?, ?>> livingTasks = new ArrayList<>(); /** * Call cancel on all tasks and then wipe the living task list. */ public static void cancelTasks() { synchronized (livingTasks) { for (AsyncTask task : livingTasks) { task.cancel(true); } livingTasks.clear(); } } /** * Before executing add the task to list of managed tasks. */ @Override protected void onPreExecute() { super.onPreExecute(); synchronized (livingTasks) { livingTasks.add(this); } } /** * On execution completion remove task from managed task list. */ @Override protected void onPostExecute(Result result) { super.onPostExecute(result); synchronized (livingTasks) { livingTasks.remove(this); } } /** * On task cancellation remove task from managed task list. */ @Override protected void onCancelled() { super.onCancelled(); synchronized (livingTasks) { livingTasks.remove(this); } } /** * Uses true parallelization to execute async tasks, requires extreme care * with data synchronization! */ public void executeParallel(Params... params) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); } else { execute(params); } } }