2

Here is my issue: I have a list of values which I retrieve from server. These values fill ListView in the UI. I cannot continue loading the View and showing it to user until the list is full. Since Android forces me to make http calls in separate thread, my question is how do I create 1 class that does the httprequests and in the calling class I wait until I get response from the HttpRequest and only then I proceed loading the View? Right now I have this class that does the requests:

public class WapConnector extends AsyncTask<String, String, String>{
private static final String TAG = "WapConnector";
private String html = "";
private Handler mHandler;
private String server = "http://....whatever";
private String callUrl = "/api/";
private String params = "login?u=Admin&pw=234234&format=json";
private int _callstate = 1;


@Override
protected String doInBackground(String... uri) {
    HttpClient httpclient = new DefaultHttpClient();
    HttpResponse response;
    String responseString = null;
    try {
        String fullUrl = "";
        Log.i(TAG,fullUrl);
        if(params.length() > 0){
            fullUrl = server + callUrl + params + "&alf_ticket=" + Globals.getInstance().getTicket() + "&udid=" + Globals.getInstance().udid() + "&phoneNumber=" + Globals.getInstance().phoneNumber();
        }
        else{
            fullUrl = server + callUrl + "?udid=" + Globals.getInstance().udid() + "&alf_ticket=" + Globals.getInstance().getTicket() + "&phoneNumber=" + Globals.getInstance().phoneNumber();
        }
        Log.i(TAG,fullUrl);
        response = httpclient.execute(new HttpGet(fullUrl));
        StatusLine statusLine = response.getStatusLine();
        if(statusLine.getStatusCode() == HttpStatus.SC_OK){
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            response.getEntity().writeTo(out);
            out.close();
            responseString = out.toString();
            Log.i(TAG,responseString);
        } else{
            //Closes the connection.
            response.getEntity().getContent().close();
            throw new IOException(statusLine.getReasonPhrase());
        }
    } catch (ClientProtocolException e) {
        e.printStackTrace();
        //TODO Handle problems..
    } catch (IOException e) {
        //TODO Handle problems..
        e.printStackTrace();
    }
    return responseString;
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    Log.i(TAG + "onPostExecute",result);
    activity.getClass().handleResponse();
        //main load
        JSONObject jobj;
        JSONObject jvalue;
        try {
            jobj = new JSONObject(result);
            if(_callstate == 1){
                jvalue = jobj.getJSONObject("data");
                String ticket = jvalue.getString("ticket");
                Log.i("loginwap",ticket);
                Globals.getInstance().setTicket(ticket);
                _callstate = 2;
            }
            else{
                jvalue = jobj.getJSONObject("countries");
                JSONArray countries = jvalue.getJSONArray("countries");

            }
        }
        catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
}

And this is how I make calls from Parent classes:

WapConnector wap = new WapConnector();
    wap.setCallUrl("/anyurl/");
    wap.callstate(3);
    wap.setParams("");
    wap.execute("");

Now my issue is that since the request runs in thread, once I call wap.execute(), my Activity continues to load, but I want it to wait until I get response, parse the response and only then continue to load.

thanks everyone for replies.!!!

Gal Blank
  • 2,070
  • 2
  • 18
  • 18
  • HAHAHA, sorry but the whole point of doing your request in another thread was so that it wouldn't wait. Just put the request in your onCreate method... – L7ColWinters Jan 31 '12 at 14:55
  • How does showing ProgressDialog helping? I really don't want to create requests methods in every class that I need to make an httprequest. There must be a way to make this more Object Oriented than that, even iOs have this.... comon guys... – Gal Blank Jan 31 '12 at 15:03
  • You *really* do not want to perform a bocking request on the UI thread. Android will give your user the dreaded Application Not Responding (ANR) error if you tie up the UI thread for more than 10 seconds, and you cannot be sure that a blocking network call will finish within that time, particularly on a slow data connection. You really need to rethink what you're trying to do. – Mark Allison Jan 31 '12 at 15:29
  • Personally what he is doing makes sense to me. Say you are developing an app that has server side profiles, but you want to show profile data in multiple activities. You don't want to rewrite that AsyncTask for every activity to get a users profile data, but you'll want to update the Activity's UI after you get the profile data. I think that is what he is asking. – onit Jan 31 '12 at 15:53
  • that is exactly what I'm trying to do Onit! thanks – Gal Blank Jan 31 '12 at 20:36
  • @GalBlank Check out my answer below then. It will work for what you want. You need to write the update UI code in a Handler that expects a message with an object attached that encapsulates all the data you need, and the AsyncTask will need to be passed in the Handler on construction and then send a message to the Handler in onPostExecute. – onit Jan 31 '12 at 21:55

1 Answers1

0

Pass in a context to your class from the activity you are calling it from. Overload the onPreExecute() to show a ProgressDialog and then overload onPostExecute() to hide the ProgressDialog. This gives you blocking while letting the user you are loading.

There is a kinda hacky way to get more control. If you want to keep the AsyncTask as a separate class but allow it to update UI elements in another Activity, define a Handler in that Activity and then pass it in the constructor of the the AsyncTask. You can then send a message in the onPostExecute() method of your AsyncTask to the handler to tell it to update the UI. You will need to make sure the handler is properly handling the message your AsyncTask is sending back. Could be a little cleaner, but it works and will allow you to reuse an asyncTask that makes a network call across activities.

onit
  • 6,306
  • 3
  • 24
  • 31