Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7755247
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 1, 20262026-06-01T12:31:14+00:00 2026-06-01T12:31:14+00:00

My goal is to have an AsyncTask that can execute multiple times (one task

  • 0

My goal is to have an AsyncTask that

  • can execute multiple times (one task at a time of course)
  • its current task can be cancelled
  • can be used by any activity
  • can execute many different tasks
  • does not have any problem with screen rotation (or phonecalls etc)

To achieve that i have created the classes shown below. But my experience with (and understanding of) threads is very limited. And since i don’t know of any way to debug multiple threads, there is no way (for me) of knowing if this is going to work or not. So what i’m really asking is: Is this code ok?

And since there is no code that it is currently using this, here’s an example use for it:

Data2Get d2g = new Data2Get(this, Data2Get.OpCountNumbers);
d2g.setParam("up2Num", String.valueOf(800));
LongOpsRunner.getLongOpsRunner().runOp(d2g);

So, here we go. This is the interface that every activity that wants to execute a long task (operation – op) should implement:

public interface LongOpsActivity {
    public void onTaskCompleted(OpResult result);
}

This is a class to enclose any result of any task:

public class OpResult {

    public LongOpsActivity forActivity;
    public int opType;
    public Object result;

    public OpResult(LongOpsActivity forActivity, int opType, Object result){
        this.forActivity = forActivity;
        this.opType = opType;
        this.result = result;
    }
}

And finally the big part, the singleton async task class:

import java.util.HashMap;
import java.util.Map.Entry;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import android.os.AsyncTask;

public class LongOpsRunner extends AsyncTask<Void, OpResult, Void> {

    public class Data2Get implements Cloneable {

        // one id for each operation
        public static final int OpCountNumbers = 1;
        public static final int OpCountLetters = 2;

        public LongOpsActivity forActivity;
        public int opType;
        private HashMap<String, String> params = new HashMap<String, String>();

        public Data2Get(LongOpsActivity forActivity, int opType) {
            this.forActivity = forActivity;
            this.opType = opType;
        }

        public void setParam(String key, String value) {
            params.put(key, value);
        }

        public String getParam(String key) {
            return params.get(key);
        }

        public void clearParams() {
            params.clear();
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            // deep clone
            Data2Get myClone = (Data2Get) super.clone();
            myClone.clearParams();
            for (Entry<String, String> entry : params.entrySet()) {
                myClone.setParam(new String(entry.getKey()), new String(entry.getValue()));
            }
            return myClone;
        }
    }

    private class IntermediateResult extends OpResult {

        public IntermediateResult(LongOpsActivity forActivity, int opType, Object result) {
            super(forActivity, opType, result);
        }
    }

    // not really needed
    private class FinalResult extends OpResult {

        public FinalResult(LongOpsActivity forActivity, int opType, Object result) {
            super(forActivity, opType, result);
        }
    }

    private final ReentrantLock lock = new ReentrantLock();
    private final Condition executeOp = lock.newCondition();
    private volatile boolean finished = false;
    private volatile boolean waiting = true;
    private volatile boolean shouldCancel = false;
    private volatile boolean activityHasBeenNotified = true;
    private Data2Get startingOpParams = null;
    private Data2Get currentOpParams = null;
    private FinalResult currentOpResult;

    protected Void doInBackground(Void... nothing) {

        try {
            lock.lockInterruptibly();

            do {
                waiting = true;
                while (waiting) {
                    executeOp.await();
                }

                shouldCancel = false;
                activityHasBeenNotified = false;
                boolean opCancelled = false;
                try {
                    currentOpParams = (Data2Get) startingOpParams.clone();
                } catch (CloneNotSupportedException cns) {
                    // do nothing
                }

                switch (currentOpParams.opType) {
                case Data2Get.OpCountNumbers:
                    int numberCounter = 0;
                    int numLoopCount = 0;
                    while ((!opCancelled) & (numLoopCount <= 5000000)) {
                        if (!shouldCancel) {
                            numberCounter = (numberCounter + 1)
                                    % Integer.parseInt(currentOpParams.getParam("up2Num"));
                            if (numberCounter == 0) {
                                numLoopCount++;
                                publishProgress(new IntermediateResult(
                                        currentOpParams.forActivity,
                                        currentOpParams.opType,
                                        "Numbers loop count:" + numLoopCount));
                            }
                        } else {
                            opCancelled = true;
                            activityHasBeenNotified = true;
                        }
                        if (!opCancelled) {
                            currentOpResult = new FinalResult(
                                    currentOpParams.forActivity,
                                    currentOpParams.opType,
                                    "Numbers loop completed.");
                            publishProgress(currentOpResult);
                        }
                    }
                    break;
                case Data2Get.OpCountLetters:
                    int letterLoopCount = 0;
                    char ch = 'a';
                    while (!opCancelled & (letterLoopCount <= 5000000)) {
                        if (!shouldCancel) {
                            ch++;
                            if (Character.toString(ch).equals(currentOpParams.getParam("up2Letter"))) {
                                ch = 'a';
                                letterLoopCount++;
                                publishProgress(new IntermediateResult(
                                        currentOpParams.forActivity,
                                        currentOpParams.opType,
                                        "Letters loop count:" + letterLoopCount));
                            }
                        } else {
                            opCancelled = true;
                            activityHasBeenNotified = true;
                        }
                        if (!opCancelled) {
                            currentOpResult = new FinalResult(
                                    currentOpParams.forActivity,
                                    currentOpParams.opType,
                                    "Letters loop completed.");
                            publishProgress(currentOpResult);
                        }
                    }
                    break;
                default:
                }

            } while (!finished);

            lock.unlock();
        } catch (InterruptedException e) {
            // do nothing
        }
        return null;
    }

    public void cancelCurrentOp() {
        shouldCancel = true;
    }

    @Override
    protected void onProgressUpdate(OpResult... res) {
        OpResult result = res[0];
        if (result instanceof IntermediateResult) {
            // normal progress update
            // use result.forActivity to show something in the activity
        } else {
            notifyActivityOpCompleted(result);
        }
    }

    public boolean currentOpIsFinished() {
        return waiting;
    }

    public void runOp(Data2Get d2g) {
        // Call this to run an operation
        // Should check first currentOpIsFinished() most of the times
        startingOpParams = d2g;
        waiting = false;
        executeOp.signal();
    }

    public void terminateAsyncTask() {
        // The task will only finish when we call this method
        finished = true;
        lock.unlock(); // won't this throw an exception?
    }

    protected void onCancelled() {
        // Make sure we clean up if the task is killed
        terminateAsyncTask();
    }

    // if phone is rotated, use setActivity(null) inside
    // onRetainNonConfigurationInstance()
    // and setActivity(this) inside the constructor
    // and all that only if there is an operation still running
    public void setActivity(LongOpsActivity activity) {
        currentOpParams.forActivity = activity;
        if (currentOpIsFinished() & (!activityHasBeenNotified)) {
            notifyActivityOpCompleted(currentOpResult);
        }
    }

    private void notifyActivityOpCompleted(OpResult result) {
        if (currentOpParams.forActivity != null) {
            currentOpParams.forActivity.onTaskCompleted(result);
            activityHasBeenNotified = true;
        }
    }

    private static LongOpsRunner ref;

    private LongOpsRunner() {
        this.execute();
    }

    public static synchronized LongOpsRunner getLongOpsRunner() {
        if (ref == null)
            ref = new LongOpsRunner();
        return ref;
    }

    public Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

}

I hope someone helps with making this work, as it would be very useful not only for me, but many other people out there. Thank you.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-01T12:31:16+00:00Added an answer on June 1, 2026 at 12:31 pm

    Try Loaders. I switched from simple AsyncTasks to AsyncTaskLoaders and they solve lots of problems. If you implement a Loader as a standalone class, it would meet all of your requirements, especially when it comes to rotation which is the biggest issue with old AsyncTask.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

The Goal is to have a list of options (that a user can chose
My ultimate goal is to have a menu that adds a class to the
My goal is to have one element on initial load, this element should have
My goal is to have multiple mp4's stores in different folders on a server.
The end goal is to have some form of a data structure that stores
Goal : I have a view which displays multiple nodes in full view including
In my application, I have 2 list activities which can start one or the
I have a Linq query that orders by a datetimeoffest. The goal is to
At the moment, I have a goal of writing an application that contains a
I am creating domain model. I have Goal ( something that user wants to

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.