Android: How multiple separate async tasks work? - android

In my Android program, I have to do 4 or 5 network calls. Each are independent, and each can run on their own.
public void backGroundTasks() {
new AsyncTasks<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
List<User> users = RetrofitAdapter.getClient().getUsersSync();
saveToDB(users);
} catch (RetrofitError error) {
error.printStackTrace();
}
return null;
}
}.execute();
new AsyncTasks<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
List<Media> contents = RetrofitAdapter.getClient().getContentsSync();
saveToDB(contents);
} catch (RetrofitError error) {
error.printStackTrace();
}
return null;
}
}.execute();
new AsyncTasks<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
Profile profile = RetrofitAdapter.getClient().getProfile();
saveToDB(profile);
} catch (RetrofitError error) {
error.printStackTrace();
}
return null;
}
}.execute();
new AsyncTasks<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
List<Message> messages = RetrofitAdapter.getClient().getMessages();
saveToDB(messages);
} catch (RetrofitError error) {
error.printStackTrace();
}
return null;
}
}.execute();
}
My questions are,
How this AsyncTask work ?
Will be executed in parallel ? or Will be invoked but the network requests will be queued ?
In some SO answers they have mentioned to do execute AsyncTasks with executeOnExecutor(). Will it help for this scenario ?
Note:
I use Retrofit library for making REST calls easier. Does it have anything with this problem ?

How this AsyncTask work ? Will be executed in parallel ?
Since honeycomb they will be executed serially, but if you will use executeOnExecutor then they will be executed in parallel.
or Will be invoked but the network requests will be queued ?
they will be queued, no network operation will start untill AsyncTask will get its turn.
Internally AsyncTasks use Executors. Your tasks only execute network operation, so you might switch to Executors. If you want to do your network operations serially, then you might also consider using IntentService.

This is answer by Arhimed. He explained it well.
AsyncTask uses a thread pool pattern for running the stuff from doInBackground(). The issue is initially (in early Android OS versions) the pool size was just 1, meaning no parallel computations for a bunch of AsyncTasks. But later they fixed that and now the size is 5, so at most 5 AsyncTasks can run simultaneously. Unfortunately I don't remember in what version exactly they changed that.
For more check his answer

Executors with AsyncTasks works like charm. It executes the network requests concurrently.
From the docs,
Since Honeycomb, invoking AsyncTask's executeOnExecutor() instead of execute() will execute tasks in parallel.
AsyncTask.THREAD_POOL_EXECUTOR
An Executor that can be used to execute tasks in parallel.

Related

Android AsyncTask terminated before completion if connection or device is slow

I have an AsyncTask where I invoke a method that download some data from internet and performs certain operations.
In the emulator this works always despite the connection speed but on real devices if connection or device isn't fast this task is automatically terminated. I don't know why, but probably there is some kind of default timeout in Android default task management.
How could I fix this problem?
How to force the completion of the task always?
Here my code
myTask = new AsyncTask<Void, Void, Void>() {
ProgressDialog pd;
boolean correctlyInitialized = true;
#Override
protected void onPreExecute() {
pd= new ProgressDialog(CatcherTree.this);
pd.setCancelable(false);
try {
pd.show();
} catch (Error e) {
e.printStackTrace();
}
}
#Override
protected Void doInBackground(Void... params) {
long t = System.currentTimeMillis();
//this method requires time to complete
updateAllDataSet(CatcherTree.this);
return null;
}
#Override
protected void onPostExecute(Void rate) {
pd.dismiss();
}
}.execute();
AsyncTasks rely on a worker thread to do the background job, and threads do not just disappear. So my guess is that the worker thread is throwing an exception and terminating.
Look through your logcat for the exception, or better yet - handle exceptions correctly in updateAllDataSet().

AsyncTask Workflow

I am currently working on an android application that has to handle a network connection using several AsyncTasks.
This is the first task that is establishing the connection and calling a new task which is handling the microphone input.
private class establishConnectionTask extends
AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
try {
// initialize connection
initConnection();
MicrophoneTask micTask = new MicrophoneTask();
micTask.execute("");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
mReadInputTask = new readInputTask();
mReadInputTask.execute("");
super.onPostExecute(result);
}
Everything works fine, the connection is working and I can transfer data. Also the MicrophoneTask is doing it's job.
Here comes the problem:
In the onPostExecute method I am creating a new AsyncTask which should handle all the network input.
This is how the readInputTask looks like:
private class readInputTask extends AsyncTask<String, Integer, String>
{
#Override
protected void onPreExecute()
{
Log.d("DEBUG", "pre");
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
// blocking readInput method
Log.d("DEBUG", "doInBackground");
}
#Override
protected void onPostExecute(String result) {
Log.d("DEBUG", "post");
super.onPostExecute(result);
}
}
The readInputTask somehow gets stuck in the onPreExecute method of the readInputTask. The only output I get is "pre", eventhough I also expect "doInBackground" and "post".
Does anyone see an error or knows a solution for this?
Any help is appreciated!
mReadInputTask.execute("");
When you use AsyncTask#execute(params), the AsyncTasks are executed serially: one after the other. To execute AsyncTasks in parallel, use AsyncTask#executeOnExecutor(...).
From the docs on executeOnExecutor (Executor exec, Params... params):
This method is typically used with THREAD_POOL_EXECUTOR to allow
multiple tasks to run in parallel on a pool of threads managed by
AsyncTask, however you can also use your own Executor for custom
behavior.

ASyncTasks blocking others

I've 2 ASyncTasks, one retrieves a value from an httpPost and the other update some elements of the UI (including an listview).
The problem is that since both ASyncTasks share the same background thread, if the network opperation start first and runs slow (due a bad network connectivity). The others background thread takes too much time making the app irresponsible.
Since both ASyncTasks are independient is pretty stupid one to make wait the other. It would be more logical asynctasks different classes use different threads, am I wrong?
Reading the ASyncTask doc. Talks about using executeOnExecutor(), but how can I solve that in a API level lower than 11?
Here goes a small example that reproduces the "problem"
new Task1().execute();
new Task2().execute();
With
public class Task1 extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
GLog.e("doInBackground start 1");
SystemClock.sleep(9000);
GLog.e("doInBackground end 1");
return null;
}
#Override
protected void onPreExecute() {
GLog.e("onPreExecute 1");
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
GLog.e("onPostExecute 1");
super.onPostExecute(result);
}
}
public class Task2 extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
GLog.e("onPreExecute 2");
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
GLog.e("doInBackground start 2");
SystemClock.sleep(9000);
GLog.e("doInBackground end 2");
return null;
}
#Override
protected void onPostExecute(Void result) {
GLog.e("onPostExecute 2");
super.onPostExecute(result);
}
}
This is how I handle this in my code:
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
new MyAsyncTask().execute();
}
And replace MyAsyncTask with yours Task1 and Task2 respectively. Basically change in AsyncTask appeared in Honeycomb (see Android SDK docs here in "Order of execution" section), so before that, you launch it as usual, for HC and up, use executeOnExecutor() if you do not like new behaviour (noone does, I think)
A slightly more general way to do this is to put two helper methods in a utility class like so:
class Utils {
#SuppressLint("NewApi")
public static <P, T extends AsyncTask<P, ?, ?>> void execute(T task, P... params) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
} else {
task.execute(params);
}
}
}
Then you can execute tasks with Utils.execute(mytask) or Utils.execute(mytask, params) and it will take care of executing them in parallel.
The problem is that every AsyncTask run in the same ThreadPoolExecutor which is coded into the API. This ThreadPoolExecutor can create a different number of WorkerThread depending on your Android version. I don't remember the number versions but the idea is that in older Android versions it was 1 WorkerThread. Then it was updated to 5 in later versions. And recently got moved back to 1 again. This is why your AsyncTasks are blocked. They run all on the same WorkerThread and thus they execute sequentially. Try using executeOnExecutor with THREAD_POOL_EXECUTOR to achieve true parallel execution. However you can use this only since API 11.

How to work with AsyncTask and threads?

The goal:
Using Google App Engine server and Android client, I'm trying to put on the Google map at the Android client Users overlays. Every 30 seconds I'm polling the server and getting Vector that contains users and adding it to the map.
Current status:
I'm dong all that using in one new thread, So after running the app I got:
weird behaviors(delayed overlays, multiple overlays) and after that crushed with ConcurrentModificationException.
After reading a bit i figured out that I need to work with AsyncTask.
Correct me if I'm wrong,But I understand that everything done in the Activity at at onCreate is "running" in UIhread so I need to put the "Logic" (All the Network handling) in doInBackground and all the UI Handling like putting overlays on the map in onPostExecute.
My Question are:
1) In the current status I'm doing:
new Thread()
{
#Override
public void run()
{
super.run();
while(true)
{
SystemClock.sleep(30000);
Vector responseFromServer = getUsersVectorFromServer();
putNewOnlineUserOnTheMap();
}
}
}.start();
What is the right way to convert this To AsyncTask?
Do I poll the server still using new thread in the doInBackground or there is right way to do this?
2) Is there a specific list of what counts as UI to put in onPostExecute or any concepts list?
In my case I guess that in need to put putNewOnlineUserOnTheMap() in onPostExecute.
Thanks.
Something similar to the following:
class UpdateTask extends AsyncTask<Void, Vector, Void>{
#Override
protected Void doInBackground(Void... params) {
// this is running in a background thread.
while (!isCancelled()) {
SystemClock.sleep(30000);
Vector responseFromServer = getUsersVectorFromServer();
// send the result back to the UI thread
// onProgressUpdate will be called then
publishProgress(responseFromServer);
}
return null;
}
#Override
protected void onProgressUpdate(Vector... values) {
// this is executed on the UI thread where we can safely touch UI stuff
putNewOnlineUserOnTheMap(values[0]);
}
}
You can't use the result of the task since the task is finished then. But you can use the progress publishing mechanism to get periodic results. If you use it like that and do the modification on the UI thread you should not get ConcurrentModificationException because you do the modifications on the one thread that can safely modify the UI.
One thing to note here: create new instances of your Vector in the background thread and then use it to update the UI. But don't touch the same object afterwards in the backgroundthread. That way you don't need any synchronization since after the background thread sends it away it is only the UI thread that touches it. (and you could use a simple ArrayList instead of a Vector)
AsyncTask uses generics and varargs.The parameters that are passed to the asyntask are . TypeOfVariableArgumentsParameters is passed into the doInBackground(), ProgressParam is used for progress information and ResultParam must be returned from doInBackground() and is passed to onPostExecute() as parameter.
example:--
protected class ParsingTask extends AsyncTask> {
private ProgressDialog loadingDialog = new ProgressDialog(JsonParserActivity.this);
protected void onPreExecute() {
loadingDialog.setMessage("loading app store..");
loadingDialog.show();
}
#Override
protected ArrayList<Items> doInBackground( Context... params ) {
// do ur process here.
return result;
}
if (!this.isCancelled()) {
}
return result;
}
#Override
protected void onProgressUpdate(String... s) {
super.onProgressUpdate(s);
Toast.makeText(getApplicationContext(), s[0], Toast.LENGTH_SHORT).show();
}
#Override
protected void onPostExecute( ArrayList<Items> response ) {
//if u r dealing with list view and adapters set the adapter here at the onPostExecute()
loadingDialog.dismiss();
}
#Override
protected void onCancelled() {
super.onCancelled();
Toast.makeText(getApplicationContext(), "The operation was cancelled", 1).show();
}
}
You can use AsyncTask like below. Hope this will help you..
Class YourClass{
void YourClass(){
NetworkTask nT = new NetworkTasK();
nT.execute();
}
}
protected class NetworkTask extends AsyncTask<Void, String, Boolean>
{
#Override
protected Boolean doInBackground(Void... params)
{
try
{
String response;
while(keepreceiving)
{
response = in.readLine();//Prog Counter stops here until getting i/p.
if(response != null)
yourFunctionForResponse(response);
}
}
catch (Exception ex)
{
}
return null;
}
private void yourFunctionForResponse(String response){
//things to do....
}
}
You may also try runOnUiThread(Runnable action) along with this to implement your work.

sequencing asynctasks

I understand that http requests should be run as part of an AsyncTask to keep it off the the UI thread. But what about the case where multiple and sequential http requests may be necessary, where the latter http requests depend on the earlier, and therefore need to be run sequentially?
In this case, is it best to put the latter AsyncTasks in the onPostExecute of the earlier AsyncTasks, to make them run sequentially?
Or does this indicate that I have the wrong approach?
To make a lot of HTTPRequests in a queue, try this:
private class QueueExample extends AsyncTask<URL, InputStream, Long> {
protected Long doInBackground(URL... urls) {
SynchronousQueue<URL> queue = new SynchronousQueue<URL>();
for(URL url : urls){
queue.add(url);
}
for (URL url : queue) {
InputStream in = new BufferedInputStream(queue.take().openConnection().getInputStream());
publishProgress(in);
}
}
protected void onProgressUpdate(InputStream... progress) {
doSomethingWithStream(progress[0]);
//Do Something
}
protected void onPostExecute(Long result) {
//Finished
}
}
If you don't have to update the UI between requests, just execute them one after another in doInBackground() and accumulate the results. When done, just return and use the result in onPostExecute() to update the UI. If you do need to update the UI, you can call publishProgress when you get some intermediate result and update in onProgressUpdate().

Categories

Resources