Android wait AsyncTask to finish - android

I have a function, AppHelper.isOnline(Context context), I call in various parts of my application to check that a session didn't timeout before making an HTTP request.
public void onClick(View v) {
Intent intent = null;
switch (v.getId()) {
case R.id.buttonPagamenti:
if (AppHelper.isOnline(this))
{
//here AppHelper.isOnline should have finished it's async task
intent = new Intent(this, OrdineCreaActivity.class);
this.startActivityForResult(intent, R.id.buttonPagamenti);
}
break;
...
Inside AppHelper.isOnline(), I am executing an AsyncTask that logs in, thus making a network request, which can't be run on UI because otherwise I get an exception. I need to wait for it to finish BEFORE resuming with the code inside the if. How can I do this ?
Problem is the activity starts firsts, then the AsyncTask executes, so when the activity expects a valid logged in session, it breaks.

You have two options:
Either use the AsyncTask's method get(long timeout, TimeUnit unit) like that:
task.get(1000, TimeUnit.MILLISECONDS);
This will make your main thread wait for the result of the AsyncTask at most 1000 milliseconds (as per #user1028741 comment: actually there is also infinetly waiting method - AsyncTask#get() which might also do the work for you in some cases).
Alternatively you can show a progress dialog in the async task until it finishes. See this thread (No need for me to copy past the code). Basically a progress dialog is shown while the async task runs and is hidden when it finishes.
You have even third option:" if Thread is sufficient for your needs you can just use its join method. However, if the task is taking a long while you will still need to show a progress dialog, otherwise you will get an exception because of the main thread being inactive for too long.

try using
if (AppHelper.isOnline(this))
{
while(!task.isCancelled()){
// waiting until finished protected String[] doInBackground(Void... params)
}
intent = new Intent(this, OrdineCreaActivity.class);
this.startActivityForResult(intent, R.id.buttonPagamenti);
}
For more information read http://developer.android.com/reference/android/os/AsyncTask.html

Rafiq's response did not work for me - the app hung. I think the reason has to do with the nature of isCancelled(): "Returns true if this task was cancelled before it completed normally." If the task completes normally (i.e. is not cancelled) then while(!task.isCancelled()) { } will loop forever.
To solve this create a Boolean flag that you instatiate to false and then flip to true in task.onPostExecute(). Then do while(!flag) { } before switching Activities. Additionally, if you'd like to give the main thread a 'break' to let the AsyncTask process a little faster, you can do try this:
while (!flag) {
try { Thread.sleep(100); }
catch (InterruptedException e) { e.printStackTrace(); }
}
It seems to be working well for me.

intent = new Intent(this, OrdineCreaActivity.class);
context.startActivityForResult(intent, R.id.buttonPagamenti);
Write the above lines in onPostExecute() of you AysncTask. Because if we are using AsyncTask it wont wait there until the task complete.

Related

How to run a code when all threads are done

I am new to threading and i went through many post in stack overflow and find many solution for my problem but i am not sure which one is best for which condition.
First thing first, my problem is that i want to update one JSON file
when all threads are done with the bitmap generation at a specific path so
that i can get that all those image and update JSON file. So in
simple word my i want to run some code when all thread are done with it
execution and major requirement is that i don't want my main to be blocked because of this.
What i have found out
thread. join
excutorServive
android-priority-jobQueue (link)
Mutex in threadpool ( also let me know if any other is there)
I am confused which one is the best way to tackle my problem. if any
android expert out there can summarise that for following the two
scenerio what is the best available in android.
wait till when all thread completes
don't wait and get informed when all completes
You can have counter for your threads, after each thread is complete check how many have already completed, if not all completed, increment the number of completed threads and the last thread to complete will then run the piece of code.
You can do it like this.
In your thread:
private Runnable runnableThread= new Runnable() {
#Override
public void run() {
try {
if (lastThreadDone){
handler.sendEmptyMessage("SUCCESS");
}
}
catch (Exception ex) {
throws ex;
}
}
};
lastThreadDone is boolean which will become true if the process is done, this is base on how you implement it.
then in you handler:
#SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
try {
switch (msg.what) {
case "SUCCESS": {
// your code here
break;
}
case "FAIL":
break;
default:
break;
}
}
catch (Exception ex) {
throw ex;
}
super.handleMessage(msg);
}
};
I would use a completion service and then poll until all tasks are finished. When they are done, the json file gets updated. The problem is that you need to do this async or you risk to block the ui. Therefore I would encapsulate the work with the completion service inside an intent service. If you need to update the ui you then can post local broadcasts from the intent service.
Furthermore for you cases
wait till when all thread completes
only do this when you are already on a background thread like intent service or async task
don't wait and get informed when all completes
implies the case above. Do the work async and notify the ui or some listening component with broadcasts, content observers, handlers or the 'onPostExecute' if you are using async task.

Android AsyncTask waiting/queued

I have a class extending an AsyncTask that sends messages to a WCF web service. Simple messages one by one will work fine, but if I send a message on a new thread that takes 30 seconds to complete, then midway through that I send a quick request it won't execute the AsyncTask until the long one has returned.
I thought the whole idea of AsyncTask was these two messages would run on different threads and therefore wouldn't stack?
Here is my code:
private class RunnableTask extends AsyncTask<RunnableObj, RunnableObj, RunnableObj> {
#Override
protected RunnableObj doInBackground(RunnableObj... params) {
try {
if (params[0].requestBody != (null)) {
params[0].request.body(new JSONObject(params[0].requestBody));
}
params[0].request.asVoid();
return params[0];
}
catch (Throwable e) {
params[0].handler.onFailure(e);
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(RunnableObj runnableObj) {
super.onPostExecute(runnableObj);
runnableObj.handler.onSuccess();
}
}
This is my AsyncTask above.
public void put(final String urlStr, final String requestBody, final HttpResponseHandler httpResponseHandler) {
RunnableObj obj = new RunnableObj();
obj.handler = httpResponseHandler;
obj.request = webb.put(urlStr)
.header(ServiceConstants.SessionTokenHeader, MyApplication.getSessionToken())
.ensureSuccess();
obj.requestBody = requestBody;
new RunnableTask().execute(obj);
}
This is the method I use to call the Async.
As you can see in the method I use to call the service, I initialise a new instance of RunnableTask each time.
How it performs:
The long request will go to the web service and start it's 30 seconds of doing things.
10 seconds later my quick little PUT creates it's object, then the last thing the debugger shows is the break point on the "new RunnableTask().execute(obj);" line and then it just disappears.
20 seconds later the first line of my RunnableTasks doInBackground method will hit and it will perform the PUT.
Please can someone help? Or at least tell me I'm doing something very stupid..
You can execute multiple AsyncTask by using executeOnExecutor
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
new MyAsyncTask().execute();
}
For more check the AsyncTask documentation
According to the AsyncTask Docs:
When first introduced, AsyncTasks were executed serially on a single
background thread. Starting with DONUT, this was changed to a pool of
threads allowing multiple tasks to operate in parallel. Starting with
HONEYCOMB, tasks are executed on a single thread to avoid common
application errors caused by parallel execution.
If you truly want parallel execution, you can invoke
executeOnExecutor(java.util.concurrent.Executor, Object[]) with
THREAD_POOL_EXECUTOR.
As you can see, AsyncTasks currently only operate on a single background thread, meaning multiple queued tasks will have to fire one after another. If you would like to execute concurrent tasks, you'll want to follow the instructions above.

AsyncTask starts after function is finished

I just have a public function where I have some loops etc. and in the beginning of my function I start my AsyncTask which returns me a value which is needed in the near of the end of this function. But somehow the AsyncTask just starts after this function finished ? Is there a way to run the Asynctask before or parallel ? Until today I thought AsyncTask are normally running parallel. I found out the method
.get()
but this is freezing the thread ... I need an alternative or fix
public void my_function ()
{
new async_task().execute()
... //do something
if (returned_value_from_async_task == 10) //Here I need the variable which is returned in the async_task
{
... //do something
}
} //End of function
//When I go to debug mode the AsyncTask starts right here
Yes. Thats the "Async" part of AsyncTask. The code at the end of the function isn't going to wait for the task to finish. so you can't rely on that data to be there. The code you're running in your function probably takes less time than it takes the ThreadPoolExecutor to spool up your task.
Execute the code that depends on the data from the AsyncTask in onPostExecute
EDIT:
Without knowing what "more complex" means, it's hard to say what your best option is. But you could split the function, thusly
public void preExecutePrep() {
YourTask yourTask = new YourTask();
yourTask.execute();
//do what you can without the result
}
private void postExecuteCode(int result) {
if (result != 10) return;
//do the rest
}
then call postExecuteCode in onPostExecute. If this isn't going to cut it, I'll need more specific information to help

AsyncTask goes into wait state

I want to cancel the Async Task on the particular condition.
I am doing the following stuff:
MyService.java
....
if(condition){
asyncTask.cancel(true); // its return the true as well
}
...
MyAsynTask.java
...
protected Object doInBackground(Object... x) {
while (/* condition */) {
// work...
if (isCancelled()){ // Here task goes in to wait state
break;
}
else{
//continue to download file
}
}
return null;
}
...
Using DDMS I found that task goes into wait State. Any suggestion to resolve this issue will be highly appreciated.
Thanks,
Yuvi
AsyncTask is a piece of work for PoolExecutor. When you execute your first task Executor creates first thread and executes your task on it. After task execution is finished the thread is not deleted. It starts waiting for a new task.
So it is normal to see AsyncTask thread in wait state.
P.S. It's better not to use AsyncTask for longtime operation. Use your own executor or thread.
P.P.S. AsyncTask uses single thread executor since 4.x. Be careful )
after you explicitly call asyncTask.cancel(true);, the onCancelled() method is called. Try overriding the following method:
#Override
protected void onCancelled() {
//what you want to do when the task was cancelled.
}

Android AsyncTask - avoid multiple instances running

I have AsyncTask that processes some background HTTP stuff. AsyncTask runs on schedule (Alarms/service) and sometime user executes it manually.
I process records from SQLite and I noticed double-posts on server which tells me that sometime scheduled task runs and at the same time user runs it manually causing same record to be read and processed from DB twice. I remove records after they processed but still get this.
How should I handle it ? Maybe organize some kind of queing?
You can execute your AsyncTask's on an Executor using executeOnExecutor()
To make sure that the threads are running in a serial fashion please use: SERIAL_EXECUTOR.
Misc: How to use an Executor
If several activities are accessing your DB why don't create a sort of gateway database helper and use the synchronized block to ensure only one thread has access to it at an instant
Or, you can try this to see if the Task is currently running or not:
if (katitsAsyncTask.getStatus().equals(AsyncTask.Status.FINISHED))
katitsAsyncTask.execute();
else
// wait until it's done.
Initialize the AsyncTask to null. Only create a new one if it is null. In onPostExecute, set it to null again, at the end. Do the same in onCancelled, in case the user cancels this. Here's some untested code to illustrate the basic idea.
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class FooActivity extends Activity {
private class MyAsyncTask extends AsyncTask<Foo, Foo, Foo> {
#Override
protected void onPostExecute(Foo foo) {
// do stuff
mMyAsyncTask = null;
}
#Override
protected void onCancelled() {
// TODO Auto-generated method stub
mMyAsyncTask = null;
}
#Override
protected Foo doInBackground(Foo... params) {
try {
// dangerous stuff
} catch (Exception e) {
// handle. Now we know we'll hit onPostExecute()
}
return null;
}
}
private MyAsyncTask mMyAsyncTask = null;
#Override
public void onCreate(Bundle bundle) {
Button button = (Button) findViewById(R.id.b2);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (mMyAsyncTask == null) {
mMyAsyncTask = new MyAsyncTask();
mMyAsyncTask.execute(null);
}
}
});
}
}
I know this was a while ago now, and you have solved your problem. but I just had a similar problem. Reno's suggestion put me on the right track, but for those who have been finding it difficult to fill in the gaps. Here is how I overcame a similar issue to that of katit's.
I wanted a particular AsyncTask to only run if it was not currently running. And as a forward from Reno's suggestion, the AsyncTask interface has been created to handle all the nitty gritty processes in properly dealing with threads for Android. Which means, the Executor is built in. As this blog suggests:
"When execute(Object.. params) is invoked on an AsyncTask the task is executed in a background thread. Depending on the platform AsyncTasks may be executed serially (pre 1.6 and potentially again in 4+), or concurrently (1.6-3.2).
To be sure of running serially or concurrently as you require, from API Level 11 onwards you can use the executeOnExecutor(Executor executor, Object.. params) method instead, and supply an executor. The platform provides two executors for convenience, accessable as AsyncTask.SERIAL_EXECUTOR and AsyncTask.THREAD_POOL_EXECUTOR respectively. "
So with this in mind, you can do thread blocking via the AsyncTask interface, it also implies you can simply use the AsyncTasks.getStatus() to handle thread blocking, as DeeV suggests on this post.
In my code, I managed this by:
Creating a global variable defined as:
private static AsyncTask<String, Integer, String> mTask = null;
And in onCreate, initialising it as an instance of my AsyncTask called CalculateSpecAndDraw:
mTask = new CalculateAndDrawSpec();
Now when ever I wish to call this AsyncTask I surround the execute with the following:
if(mTask.getStatus() == AsyncTask.Status.FINISHED){
// My AsyncTask is done and onPostExecute was called
mTask = new CalculateAndDrawSpec().execute(Integer.toString(progress));
}else if(mTask.getStatus() == AsyncTask.Status.PENDING){
mTask.execute(Integer.toString(progress));
}else{
Toast.makeText(PlaySpecActivity.this, "Please Wait..", 1000).show();
}
This spawns a new thread if it is finished, or if the thread state is PENDING, the thread is defined but has not been started we start it. But otherwise if the thread is running we don't re-run it, we simply inform the user that it is not finished, or perform what ever action we wish. Then if you wanted to schedule the next event rather than just block it from re running, take a look at this documentation on using executors.
How about just wrapping your check-what-to-send and send-it logic in a synchronized method? This approach seems to work for us.
try having some instance boolean value that gets set to "true" on the asynctask's preexecute then "false" on postexecute. Then maybe in doinbackground check if that boolean is true. if so, then call cancel on that particular duplicate task.
You could keep the state of the task in shared preferences. Check the value (Boolean perhaps) before starting the task. Set the state to finished(true?) in onPostExecute and false in onPreExecute or in the constructor

Categories

Resources