2

I have been using AsyncTask in Android for some time now. I like it because you can run asynchronously, on a background thread, any task you want (by task I mean a block of code).

At the beginning, every time a task should be run asynchronously and/or on a background thread, I bundled its code into an extension of AsyncTask. I sometimes needed to chain multiple of these tasks (one depending on the result of another) and called the next one in AsyncTask.onPostExecute(T data) (once the execution finished), but now I feel my code is cluttered by so much boilerplate code (the AsyncTask skeleton) and the coupling of successive tasks.

On top of that, my AsyncTasks are sometimes launched from another AsyncTask and Android may complain. For example if I want to display some elements in the pre/post executions, this would be a problem when nesting the calls.

In particular, I am searching a way to modularly choose whether a task should be run synchronously/asynchronously, sequentially/in parallel, or together with another. My choice so far has been to have a simple interface Task expecting an implemented execute(T data) method. Then I can bundle one or multiple of them, to run sequentially or in parallel, as defined in blocks such as this one:

public doMultipleActions() {
  runTask(new MyFirstParallelTask(myFirstData)); // running asynchronously in parallel the first task
  runTask(new MySecondParallelTask(mySecondData)); // running asynchronously in parallel the second task

  runTask(new MyFirstSequentialTask(myThirdData, new MySecondSequentialTask(myFourthData, new DummyCallback()))); // running asynchronously sequentially the third and fourth tasks
}

i.e. runTask(Task t) will run the code of Task.execute(T data) into a AsyncTask.doInBackground(T... data) block of code. Sequential tasks also expect another task to be executed in a AsyncTask.onPostExecute(T data) code block.

I have looked at multiple similar questions: Can I chain async task sequentially (starting one after the previous asynctask completes), AsyncTask chaining in Activity (callback?), How to avoid chaining several AsyncTask calls?, most approaching my issue but I could not find anything useful, even though I do not think I am the only one to deal with this.

Is there a better way, an expected way, or even a design pattern on modular usage of AsyncTask in Android?

Community
  • 1
  • 1
Vince
  • 1,570
  • 3
  • 27
  • 48

1 Answers1

1

Multiple AsyncTask can be run in serial or parallel way by using executeOnExecutor with parameter AsyncTask.SERIAL_EXECUTOR or AsyncTask.THREAD_POOL_EXECUTOR.

If you expect a result with a wait mechanism(e.g wait for a task to finish and return a result) then the better way is to use Future. One such implementation is FutureTask which relies on Callable like this:

ExecutorService pool = Executors.newFixedThreadPool(poolSize);
FutureTask<String> future = new FutureTask(new Callable() {
    public String call() {
        ...
    return res;
});
executor.execute(future);

String res = future.get(); 

The last line will block the operation until Callable inside returns its String result. In fact you can even set a timeout for it to finish.

Remember that AsyncTask doesn't only perform asynchronous operation. It also carries out its process on background thread. So you may still use an AsyncTask (or Thread) to do synchronous operations which otherwise would block the UI.

inmyth
  • 8,880
  • 4
  • 47
  • 52
  • 1
    Thanks for your suggestion, it is interesting but I don't see how it answers the question (which is more about batch processing of `AsyncTask` than about asynchronous tasks). I could improve my question. One thing also, running multiple tasks inside one `AsyncTask` is not equal to multiple `AsyncTask`, typically the multiple `AsyncTask` may run in parallel. – Vince May 19 '15 at 03:30
  • First of all AsyncTask stands for **Asynchronous** Task. Secondly, you are *searching a way to choose whether a task should be run asynchronously, after another, or together with another*, but you seem to only have AsyncTask at your disposal. In fact what you do with chaining AsyncTask is technically forming a synchronous process (where the next AsycTask waits for the former). So I infer that you are looking for a synchronous way to run a process. – inmyth May 19 '15 at 03:45
  • I see, you're right. That's not what I expected but I will read the doc to see how I can integrate it. Thanks – Vince May 19 '15 at 11:54
  • To be fair I reread your question and I get an impression think you want to do it strictly with `AsyncTask`. I updated my answer for that. AsyncTask can be made to run serially or parallelly. If you seek to do just this then `AsyncTaskexecuteOnExecutor` would do. There are caveats regarding the max number of AsycTask that can run simultaneously and different default behavior on different API. In fact if you run ICS then it's serial by default. So I'd use Future if I only seek a result and AsyncTask if want to both do a background task and update UI. – inmyth May 19 '15 at 14:55
  • Yeah I am not asking for another tool doing something close to AsyncTask, AsyncTask fits me, but how to modularly manipulate this concept. Your answer made me realise that my question does not focus on the right things (the packaging, instead of the AsyncTask tool). I have not had time to try your solution yet, I shall do that soon. – Vince May 19 '15 at 15:02
  • OK, I understood the point of a FutureTask. That's not really what I searched, I updated my question, but that's still interesting to know about it, I might use that later on. – Vince May 19 '15 at 17:44