0

I'm currently developing a application that connects to a website to get some information (very few information), and I'm using a Asynctask with a HttpClient inside of it to get this information. In the main (UI) thread, I use a runnable plus a Handler to check if the Asynctask is already finished and, if it is, process the incoming information.

Problem is: sometimes the Asynctask doesn't seem to complete the task, making the Handler plus Runnable check it forever without any answer. It's not a problem with the website, as I tested it in a local website using Xampp. It seems to me that I'm not doing something the way it's meant to be.

I "solve" the problem by forcing the app to close via my Android's app manager (the app then takes less than 1 iteration to get the information), but I wouldn't like to say to people who's gonna use it: "Hey, in case of problem, force the app to close via your app manager", I would like the app to run without problems, so I'm asking you for help. :)

Here's some code:

public class Postman extends AsyncTask<String,String,String> {

@Override
protected String doInBackground(String... s) {
    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost("http://website.com/" + s[0]);
    List<NameValuePair> pairs = new ArrayList<NameValuePair>();
    for(int i = 1; i < s.length; i++){
        pairs.add(new BasicNameValuePair(Integer.toString(i),s[i]));
    }
    try {
        post.setEntity(new UrlEncodedFormEntity(pairs));
        HttpResponse r = client.execute(post);
        String res = EntityUtils.toString(r.getEntity());
        return res;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
}

This class I use to communicate with the website. I create a Postman object then I use postman.execute("phpPageToCommunicate.php", + params);, then I use the following code to check if it's already finished or not:

final Handler h = new Handler();
Runnable r = new Runnable(){
@Override
public void run() {
    if(postman.getStatus() == AsyncTask.Status.FINISHED()){
        // some code
    }else{
        h.postDelayed(this,1000);
    }
}
};
h.postDelayed(r,1500);

I'm sure I'm doing something wrong, but I don't know what, so I'm sincerely asking you for help

Cheers!

Washington A. Ramos
  • 874
  • 1
  • 8
  • 25
  • you can keep a flag in postexceute of asynctask which says that if ur task isnt complete u can show alert dialog to user.. – KOTIOS Sep 17 '14 at 16:03
  • Instead of having another thread checking if the AsyncTask is done, why not use the OnPostExecute method to process the result and execute callbacks ? This is how AsyncTask is supposed to be used. – personne3000 Sep 17 '14 at 16:04
  • If it's an inner-class of your `Activity` then just use `onPostExecute()` as suggested. If it's a separate class then [see this answer about using an interface](http://stackoverflow.com/questions/18517400/inner-class-can-access-but-not-update-values-asynctask/18517648#18517648) to return the result to your `Activity`. You shouldn't need the `Handler` for this. – codeMagic Sep 17 '14 at 16:07
  • run in debug mode, make sure the doInBackground is executed and completed. (also use `onPostExecute`, but there may be some deeper issue here). Possibly another asynctask is keeping the asynctask executor for itself. – njzk2 Sep 17 '14 at 17:53
  • njzk2, you mean that lots of Asynctasks may produce this error? I mean, if one doesn't finish, then others won't be able to run? – Washington A. Ramos Sep 17 '14 at 20:40

3 Answers3

1

You're doing it very wrong actually. There is a method onPostExecute which you can override in your AsyncTask class and in there do what you need. Everything in that method is done on UI thread so you don't have to care about it.

The third class parameter is actually the type of result you're expecting in your onResult. So in your case you're passing <String, String, String> so your onPostExecute will be onPostExecute(String result).

cliffroot
  • 1,839
  • 17
  • 27
0

You don't need a handler here.

You should use onPostExecute from your asyncTask instead of the Handler. At least the AsyncTask will notify this method as soon as the task is executed.

http://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute(Result)

cladjules
  • 34
  • 1
0

Okay you are doing Async Task wrong

private class GetInfo extends
            AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... strUrl) {
            // Do something with strUrl 
            // Store the result in res variable(String)

            return res; //Returns this to onPostExecute
        }

        @Override
        protected void onPostExecute(String result) {
            // Set Data to View or save it
        }

    }

and in your main thread call

new GetInfo().execute(//string to process);

the doInBackground method process the data (get data from api or something in your case).. all the heavy work is done here that takes time.

the result is stored in a String and that string is returend to onPostExecute where it can be set to a view or save in a db etc..

Hope it helps..

EDIT: also there is another method called onPreExecution() that allow to initalize variables and stuff if you want to before the doInBackground method is called.

also i would like to point out <String, Void, String> , here the 1st String is the type of data Async task will get from the execute method in main thread, 2nd Void will be for doing some operations while do in backgorud is working.. like progress bar update, etc.. and 3rd String will be the type of data that doInBackground will return to postexecute method.

Plese read the documentation @developers.android for more details

Kushal Sharma
  • 5,978
  • 5
  • 25
  • 41