I know that Similar questions have been asked before but the solution to those questions will not work for me. The situation is that I have an Array of objects that are each getting sent to uploaded to the server via an asynctask. I need to send each one separately but each object in the list uses the same asynctask so calling task.execute in the onPostExecute() is not an option since that would cause it to infinitely call itself. I have tried something like so
for(each item in list){
task.execute();
while(task.getStatus() != android.os.AsyncTask.Status.FINISHED){
//spin here and wait
}
}
But when doing this it just spins for ever and never leaves the while loop.
Any suggestions are greatly appreciated
From AsyncTask docs:
Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
so if you are not >= HONEYCOMB, then maybe switch to use ExecutorService:
ExecutorService executor = Executors.newSingleThreadExecutor();
Why don't you change your architecture: Make the uploading async task take an array of files to upload and just loop through them?
If you really want to stay this way, just use a lock object.
Something like:
class MyAsyncClass extends AsyncTask{
static Object lock = new Object();
.......
void doWork(){
synchronized(lock) {
//do stuff
}
}
}
EDIT: I should point out that this does not ensure you, that the doWork() methods are executed in the order, they were called.
I suggest you should switch to Thread and Executor service to do this. This will give you greater grip on switching between sequential and parallel execution of tasks.
With the help of ExecutorService(Actually a Threadpool manager).
You can pass in the Tasks as runnable to executor service.
You can define the number of threads to be used by executor Service (For your case, make it as 1).
Example :
ExecutorService service = Executors.newFixedThreadPool(1);
service.submit(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
}
});
You can submit as many runnables to this and since the thread count is 1, it will get executed sequentially.
For communicating with UI, you can user Handler.
public void onPostExecute(){if(blahblah){
task.execute();
}
}
AKA put an if statement on task.execute so you have control..
You could look into using an IntentService, instead of an AsyncTask -- since launching multiple intents to the same IntentServicewill queue up the operations, so the Intent launched before will have to complete before the second onHandleIntent(Intent) will run.
Related
Given that posting a task with post() puts the Runnable in a queue, is there any difference between
protected void onCreate(Bundle savedInstanceState) {
Log.d("UI thread", "Do something");
}
and
protected void onCreate(Bundle savedInstanceState) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Log.d("UI thread", "Do something");
}
});
}
?
In both cases, there should only be one thread running and no concurrency happening - right?
Then what's the benefit in creating a handler that attaches to the UI thread and running tasks on it?
The timing is different. In the first snippet the code is executed as part of the onCreate execution so it is guaranteed to finish before onCreate returns, in the second snippet, it is executed some time later (maybe after several other callbacks).
Then what's the benefit in creating a handler that attaches to the UI thread and running tasks on it?
Your example provides only a minimal "use case" which most developers may never experience. In your example, you might want to start a background service but you wanted to ensure that the method that starts the service completes before performing that work, your example would accomplish that. Additionally, you might want to ensure that the service construction is prioritized on the main/UI thread. This approach means you don't have to add a comment like "put this code at the end of this method" or have other "inherent code dependencies" - the call to the handler guarantees post-method/end of method execution. Not really "normal" so...
A more useful example is when you have a background thread that needs to update the UI. It can do the necessary processing in the background, then create a handler that will execute on the UI thread appropriately. This is very common and is implemented in AsyncTask for example (in its getMainHandler() method - https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/os/AsyncTask.java#L282)
Also, handlers allow for post-delayed execution of Runnables. A post-delayed execution is often beneficial for situations where immediate screen display is more important than complete screen display. In most cases a developer should "bake-in" a delay and have the screen show a loading spinner or some other UI/UX decoration, but if there isn't a requirement to specify the length of the delay, the example you gave would post the runnable on the main thread looper queue to execute ASAP. That might be exactly what you want to do, or it might be confusing to other developers that might have to maintain your code (for example, the reason you asked this question).
From my main thread, I start an AsyncTask which will go through a list of images and for each image, it will do some processing on it. So basically, there's a for loop and inside it, another AsyncTask is called. I use an instance of a class which holds the boolean value for checking if each image is done with its processing, its called a dummyStructure.
Code of the main thread:
new BatchProcessor().execute()
the doInBackground of the BatchProcessor:
protected Void doInBackground(Void... params){
while(dummyStructure.isWorking())
{
//Try loop
thread.sleep(1000);
}
dummyStructure.setIsWorking(true); //basically sets the flag to true
for(String s: pictureList)
{
RunTheProcessingLoop().execute();
}
The Problem:
I tried debugging, and here's what the problem is imo, if I remove the line just outside the while loop dummyStrucutre.setIsWorking(true) then there are multiple asyncTasks called even before it finishes, and basically everything gets screwed up. However, if I don't remove that line, then the BatchProcessor AsyncTask gets caught in the while loop, while as the RunTheProcessingLoop AsyncTask never executes beyond its onPreExecute()(debugged to know that, I used Log.e() in every method of that asyncTask).
Definitely I'm missing something, any help? Thanks a lot! :)
What you are encountering is asynctasks getting piled up because you are starting one from another and not exiting the first. This is because the asynctasks are handled serially by a single thread by default. If you want to use multiple threads in parallel, you'd need to use your own thread executor. See the AsyncTask documentation for more details.
So after 2 days of posting this question and finding out more about what people posted, I figured this:
My main thread called for an AsyncTask and I wanted to wait for that AsyncTask to finish. So I used a boolean flag which the AsyncTask sets to false once it is done and I can queue another task. Here's the code:
class mExecutor implements Executor {
public void execute(Runnable r) {
new Thread(r).start();
}}
Now, all you need to do is, whatever task/method/etc you want to run Asynchronously, simply create a thread and push it in that class, example:
Thread t = new Thread(new Runnable() {
public void run() {
new someshit().execute();
}
});
new mExecutor().execute(t);
and Tada! Now they both won't be queued/synchronized but would run in parallel.
If I am wrong, please correct me! Thanks! :)
How do I use a thread to run some code continuously whilst an Apps running, using the information it gives to periodically update the UI of the App.
Specifically the thread would run some code that searches through a text file in order to find co-ordinates which would then be plotted over a PNG on the UI. This would update automatically say every second maybe every half second, and would clear the image then redraw the points.
How do i first of all set up the thread then second of all send information from the thread back to the UI and have it update?
Any example code would be great or any information you've come across that gives example code. I'm not trying to do it the best way at the moment, just trying to hack it together, so if you know easy and quick (but awful) ways of doing this don't feel afraid to share.
This may help u...
//on create
Thread currentThread = new Thread(this);
currentThread.start();
after on create
public void run() {
try {
Thread.sleep(4000);
threadHandler.sendEmptyMessage(0);
} catch (InterruptedException e) {
//don't forget to deal with the Exception !!!!!
}
}
private Handler threadHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
Intent in = new Intent(getApplicationContext(),****.class);
startActivity(in);
}
};
This is a very common scenario and its far boyend the scope of a simple answer to your question.
Here are two usefull links:
http://developer.android.com/guide/components/processes-and-threads.html
http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html
And there are a lot more.
Here are two different approaches for you as starting point:
Update gui from your thread, only needs syncronzation with the UI thread. Pass your Activity into your thread, it provides the method: runOnUiThread
Define an interface to provide callbacks, let the calling ui class (activity) implement your interface and register it as listener to your thread. Then you can call the callback, when ever you want. Don't for to syncronize
Try to use service(or IntentService - http://developer.android.com/guide/components/services.html) for background work and BroadcastReceiver to update the UI thread from the service.
Use the AsyncTask class (instead of Runnable). It has a method called onProgressUpdate which can affect the UI (it's invoked in the UI thread).
I have a class AsycnIntegerCounter which extends AsyncTask, with doInBackground() and onPostExecute() overridden in the same.
From my main thread, I am able to create a runnable object and execute it using the
AsycnIntegerCounter's static execute method. AsycnIntegerCounter.execute(Runnable)
Can anyone help me in understanding what exactly happens when we execute a runnable using AsycnIntegerCounter (i.e) using AsycnTask object.
When this can be used ? and what is the advantage rather than running using a Thread object?
Code Sample:
AsycnIntegerCounter integerCounter1 = new AsycnIntegerCounter(next,0);
AsycnIntegerCounter.execute(new Runnable() {
#Override
public void run() {
int i = 100;
while(i<=105){
i++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
There are a couple of fundamental differences between
static void execute(Runnable)
and
AsyncTask execute(Params...)
Background task is defined in Runnable instead of implementing doInBackground
The Runnable-task is not using the internal thread communication mechanism of the AsyncTask. Hence, neither onPreExecute nor onPostExecute are called.
The latter is available on all platforms, whereas the first was added in API level 11.
The advantage of using execute(Runnable) is that the task can be executed on a worker thread of the internal thread pool, i.e. no new thread has to be created.
It's the same as execute() but it will run your Runnable in the background instead of running the doInBackround function. It can be useful when you have the same onPreExecute and onPostExecute but several runnables.
I guess the advantage over Thread.execute or an Executor is exactly calling onPreExecute and onPostExecute before and after.
#Alex makes a very good point. Suppose the you have a lot of methods, M1(), M2(), and so on that you wish to execute. Suppose that before executing any of them you need to execute method Before() and after you need to execute method After().
ie, the sequence of methods goes:
Before();
M1();
After();
Or
Before();
M2();
After();
By putting Before() in onPreExecute and After() in onPostExecute you can achieve that sequence. By making M a runnable, you can then achieve:
Before();
WhateverRunnableYouWant();
After();
With the Runnable in a background, non-UI, thread, as per your code.
As far as i figure it's like AsyncTask class but AsynchTask only runs once, but with this class it provides two things-:
It loops so it benefits, if you want a task to run multiple time
like checking for continuous data on a web service.
It fixed the running time of a task with Thread.sleep, so if a task finished
earlier it will fix the time of this task by Thread.wait().
I'd like to have a queue of work/tasks to be done on a separate thread, but can only process one work at a time. So not simultaneously.
Is there something built-in android for this?
Thanks,
EDIT:
The work = get information from Database. Once done, update the UI with the fetched information.
Have you checked out java.util.concurrent.Executors ? You could do something like this:
final static ExecutorService tpe = Executors.newSingleThreadExecutor();
...
tpe.submit(new Runnable() {
#Override
public void run() {
// your work
}
}):
It's not android specific, it is part of the jdk5.
From the doc:
Creates an Executor that uses a single worker thread operating off an
unbounded queue. (Note however that if this single thread terminates
due to a failure during execution prior to shutdown, a new one will
take its place if needed to execute subsequent tasks.) Tasks are
guaranteed to execute sequentially, and no more than one task will be
active at any given time. Unlike the otherwise equivalent
newFixedThreadPool(1) the returned executor is guaranteed not to be
reconfigurable to use additional threads.
If you want something can do work independently from the activity lifecycle that can do queued work, you should take a look at IntentService. It can spin up, do discrete blocks of work asynchronously then finish itself when all its tasks are completed.
If you don't need anything that can live without any activities, Java has ExecutorService along with several different implementations.
In Android You can also consider about Loader framework.
http://developer.android.com/guide/components/loaders.html