Cancel all AsyncTask? - android

I have a class which is used to get media file thumbs. This Loader like class starts an AsyncTask for every ImageView (is called in SomeAdapter#getView()). The task itself does a lot of things, and one of them is calling DiskLruCache, but when the SD card is unmounted, while the tasks are still running the application crashes.
I know how to register if the card state is changed.
So I need an approach how to stop all the running tasks. Any help would be nice.

just iterate through all list & use the following which will cancel all running asynctask.
if(myAsyncTask.getStatus().equals(AsyncTask.Status.RUNNING))
{
myAsyncTask.cancel(true);
}

call cancel() on each of you asynctasks, your asynctasks must check isCancelled() for returning true and if so then return from doInBackground. This is all in AsyncTask documentation.
There is one problem with your solution, AsyncTasks are known to work in parallel on some androids and to work serially on some other. Its actually not a good idea to run them in parallel. You might consider using ExecutorService as Veaceslav Gaidarji suggested.

You can try ExecutorService look here
There are nice examples - how to start async tasks, and how to stop them at any time you need.

Related

Cancel AsyncTasks from collection

Let's say I have TasksManager which has static List tasks (not sure list is good solution) and there are static methods addTaskToList(MyTask task){tasks.add(task);},
removeTaskFromList(MyTask task){tasks.remove(task);}
Each task in doInBackground() calls first method, and in onPostExecute() there is second method call with "this".
MyTask has String field "method".
I want to cancel tasks of this list where task.getMethod().contains("url")..
not sure this code is good enough for stable working.. looks like onCancelled() of task not always called, multitreading can be dangerous for such methods I think.
for (MyTask task : tasks) {
if (task.getMethod().contains("url")) {
task.cancel(true);
break;
}
}
Is it normal practice to store tasks in this way or you can suggest me more elegant?
Cancelling an AsyncTask isn't always an immediate/obvious thing. If you are using cancel, you also need to make sure doInBackground is aware of isCancelled and you have to stop what you were doing yourself (see the docs for isCancelled).
I wouldn't recommended storing a list of AsyncTask objects and iterating them for doing sequential background work anyway. That sounds like it might get very messy very quickly. Each AsyncTask creates a new Thread, and that doesn't sound like what you want. Rather, you may just want one background thread you can do stuff on?
For one background thread you can use a HandlerThread and your own Looper, as follows:
HandlerThread backThread = new HandlerThread("BackLooper", Thread.NORM_PRIORITY);
backThread.start();
Looper backLooper = backThread.getLooper();
private synchronized void runOnBackThread(Runnable r) {
new Handler(backLooper).post(r);
}
Then each item you want to run in sequence you can post on the back thread by submitting a Runnable. And, you can also use the other Handler post variants too, postDelayed, postAt, and so on.
And, depending on what you're doing you may find IntentService very helpful. IntentService is provided specifically for a "work queue" type pattern. It has one background thread, does whatever you tell it to do ONE AT A TIME when you invoke it, and goes away on its own when it's not needed.
Lastly, if you're looking for a really nice general "task" type library for Android check out Square's Tape. That's not directly related to your question, but I find Tape super handy for more robust "queue it up" task type situations.

Two different AsyncTasks execute at the same time

I have two total different implementations of AsyncTask, lets say AT1 and AT2.
AT1 is executed first, then AT2 is executed. AT1 waits in doInBackground until AT2 has done its task by polling this data every 500 ms. But this never happens.
So what I basically want is this:
But what seems to happen is this:
Except AT1 is never done, and AT2 is never started.
Is there a way I can force these two AsyncTasks to be executed on two seperate threads, or is there another solution for this?
It is not possible to first start AT2 and after that execute AT1.
EDIT
For clarification: AT1 is executed when a user opens a particular screen, and needs to download data for that screen, based on a location. AT2 is executed on Location change, and when that happens, some calculations are made that cannot be done on the UI thread.
When AT2 has never been executed, AT1 has no location to download data for, so it needs to wait for AT2 to finish. When AT2 has been executed, the location data is already there, and AT1 doesn't need to wait.
Also, this problem occurs in ICS, not in Android 2.3, like this answer suggests.
When I posted this question, this question appeared in the Related section.
It advices to use executeOnExecutor, I've implemented this as follows:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
new SetLocationAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, location);
} else {
new SetLocationAsyncTask().execute(location);
}
What's the point of having two async tasks, if one waits for the other? And if you want to do it, why not have the first one start the second one and put the "done" stuff in the second task?
Sounds like you may need to rethink your logic - if you're kicking off a thread which then needs to wait for another thread to do some work, why not just have the first thread do that work?
If you really need 2 AsyncTasks, have the first one gather whatever data is needed and don't kick off the second until after the first is finished - have a read about onPostExecute in the docs.

Android AsyncTask inside AsyncTask

So, I'm working on a barcode decoder, which once we have the barcode goes to multiples API over the internet to decode what was just scanned.
The thing is that I have to link some XML parsing together, and I don't know if I'm doing it right.
So, once the barcode is scanned, my program calls an ASyncTask which goes over an API to retrieve the product name. Once it has the name, I want it to call another ASyncTask. I know this is possible by instantiating an ASyncTaks in the onPostExecute() of the other but, I think this is wrong, because it's like boxes within boxes.
So isn't it possible/better to instantiate my second ASyncTask inside my main Activity, and make it wait until my first ASyncTask is finished ?
(english isn't my primary language, I hope I made myself clear).
I think it's absolutely legitimate to start the second AsyncTask in the onPostExecute of the first AsyncTask, Mixing both operations is a bad logical idea, As "The Offspring" said - "You've gotta keep 'em separated"
If you don't want it to be directly inside the onPostExecute itself, set a handler to execute it in the activity and call this handler from onPostExecute.
And last thing - If you have a lot of logic - move it to a separate file, don't keep it all at the same file.
In situations like this it might be better to batch long running operations together in one AsyncTask.
Another option is to use the Loaders API, this makes chaining tasks much easier http://developer.android.com/guide/topics/fundamentals/loaders.html
You can go for another approach if you are facing often a situation like this. That is to merge requests and operations inside of runnables/callables and to manage them separately within say a queue for instance.
Here is a nice approach.
http://ugiagonzalez.com/2012/07/02/theres-life-after-asynctasks-in-android/

Async task - not clear re called methods

I have a a service class which includes an Async task. In the doInBackground and onPostExecute I call some methods which are in the service class but outside the Async task. When these methods get called will they still be in the thread created by the Async task and therefore not interfering with the main UI.
To illustrate my lack of understanding a bit more should I try to get almost everything that the service class does into the Async task. For example the service starts up as the result of an alarm and in the onStartCommand sets a repeating alarm (this is as Reto Meire's Earthquake example)and creates a database. Would it make sense to move the code for these two operations into the onPreExecute part of the Async task?
No need to do that.. make sure that the method which you want to run in background is called from doInBavkground().. rest you can put in postExecute.... the snippet which you want to run after the backGround task should be in PostExecute(). If You call methods from doInBackground() they still run on background thread.. does't matter where they are.. and if you call it from onPostExecute() then it will run on other thread which ofcourse can make changes in your display.. just like showing dialog etc...
You should always offload as much work as possible to background threads/tasks. Something like database creation should be done in the doInBackground method. The onPreExecute and onPostExecute methods run on the UI thread and are generally used to inform the user of background activity (e.g. using a ProgressDialog).
From experience, I also suggest not using a background service if you can get away with it. If you use one, you should know how to clean it up properly since users generally get annoyed with an application running in the background.

some kind of queue for asynctask

Hello
I have ListView with list of files. i click item and start to download this file in asynctask.
then i click another one and it must be put in queue, wait for that file and start ot download after it finishes. i can make some class that will hold all clicked links, and pass it to asynctask downloading part? and than somehow process them. but want to know is it the right way?
any links of sugestions? thanks
If you're set on using AsyncTask then, yeah, hold your clicked links and kick off new tasks when appropriate. You should note that AsyncTask is like the 'pocket knife' for threading in Android apps.
If you really need to manage a bunch of background tasks, and it sounds like you do, take a look at ThreadPoolExecutor. You get a lot of flexibility.
BlockingQueue
ThreadPoolExecutor
More Info
Example
Take a look at HandlerThread and the Handler class. You need one handler to pass tasks to the background HandlerThread and another for the UI thread to pass results back to the UI
Even though old, got here from Google: consider an IntentService.

Categories

Resources