4

I have an app, which uses several HTTPRequests for example

  • get a session id

  • get some locationdata

  • get existing categories

  • (...) and some more

I created a HTTPRequestHandler, which basically manages all the AsynTasks for each Request... This works well, but my problem is, I don't know a good way for managing the different AsynTasks. For example, you need to get the SessionId Task before you can start the GetSomeLocationData Task

So in my HTTPRequestHandler I have a queue, which starts the depending AsyncTasks like:

private void startSessionIdTask(...) {
    //...
    GetSessionIdTask mGetSessionIdTask = new GetSessionIdTask(this);
    mGetSessionIdTask.execute(url);
}

//and from the postExecute() in GetSessionIdTask I call
public void setSessionId(int mSessionId) {
    mDataHelper.setmSessionId(mSessionId); //set id


    String url = API_URL + API_GET_FAVORITES + URL_VARIABLE;

    List<NameValuePair> params = new LinkedList<NameValuePair>();
    params.add(new BasicNameValuePair("session_id", getSessionId()));
    String paramString = URLEncodedUtils.format(params, "utf-8");
    url += paramString;

    //and finally start another Tasks (and so one...)
    GetLocationsTask mGetLocationsTask = new GetLocationsTask(this);
    mGetSessionIdTask.execute(url);

}

However, this works fine, but the problem is, that (depending on the connection), this queue takes time, and the user can start other AsynTasks which fail, because some initially data is not loaded yet.

I could set some Boolean like isSessionIdLoaded or could block the UI for the user, but I'm wondering, if there s any better solution?!

So my question is: Is there a way to put asyntasks in some kind of queue (ArrayList, Map..) which will be executed in a row?

longi
  • 11,104
  • 10
  • 55
  • 89

3 Answers3

1

As of Android 3+ AsyncTasks will be executed in serial on the AsyncTask.SERIAL_EXECUTOR. So by default if you start 2 AsyncTasks

task1.execute();
task2.execute();

Task2 will only be executed if task1 has finished (just check the sdk implementaion of AsyncTask.SERIAL_EXECUTOR). This can be pushed to that point, that if task1 for any reason never finishes, task2 will never start and you have deadlocked your app.

If you want your own queue independed from the default SERIAL_EXECUTOR, just use

public final AsyncTask<Params, Progress, Result> executeOnExecutor (Executor exec, Params... params)

And provide your own executor (aka threadpool). For one project I copyed the SERIAL_EXECUTOR implementation to have 2 serial queues.

For Android 2.3 to 1.6 all tasks are by default in parallel, similiar to calling in Android 3+:

task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,null);

Unfortunatly in Android 2.3 und lower you have no option of specifing the executor on which the task/thread will be run on. So if you want to have it done serially, you have to implement it yourself, by calling task2 only after task1 has finished explicitly in onPostExecute(). This concept can of course be pushed to use a queue of task where the former task will call the next one when it's finished (= serial worker queue). For this you will find plenty literature and patterns.

Patrick
  • 33,984
  • 10
  • 106
  • 126
0

I'm not entirely sure what you're asking, but if you'd just like a way to queue up Runnables to execute in a background thread in sequence, then Executors.newSingleThreadExecutor() may be what you're looking for. It's more complicated than it probably needs to be, but you can find examples and tutorials easily enough via google.

Dan Breslau
  • 11,472
  • 2
  • 35
  • 44
0

If you need sequential execution, I'd recommend switching to IntentService instead of using AsyncTask. See docs: http://developer.android.com/reference/android/app/IntentService.html

Marcin Orlowski
  • 72,056
  • 11
  • 123
  • 141