6

I am trying to parse some JSON data. My code was working for awhile, and I am not sure what I changed to suddenly break the code. When I run my code I am not receiving any runtime errors or warnings. I create a new AsyncTask and execute this. When I call .get() on this new task, the debugger stalls on this line and takes more than 30 minutes. I have not been able to get the debugger or during run to complete this task.

JSON:

protected void setUp(Context context) {
    _context = context;
    getConfig();
}

// get config file
protected void getConfig() { 
    if (config != null)
        return;

    config = new Config();

    String url = configURL;
    AsyncTask<String, Integer, JSONObject> jsonTask = new DownloadJSONTask()
            .execute(url);
    JSONObject configItem = null;
    try {
        configItem = jsonTask.get(); //debugger pauses here
        if (configItem == null)
            return;
        config.configVersion = configItem.getString("field_configversion");
        config.currentAppVersion = configItem
                .getString("field_currentappversion");
        config.getSupportURL = configItem.getString("field_getsupporturl");
        config.getCatalogURL = configItem.getString("field_getcatalogurl");
        config.getDataVersion = configItem.getString("field_dataversion");
        config.getDataUrl = configItem.getString("field_dataurl");
        config.getDataApiKey = configItem.getString("field_dataapikey");
    } catch (InterruptedException e) {
        e.printStackTrace();
        System.err.println("Download of config interrupted");
    } catch (ExecutionException e) {
        e.printStackTrace();
        System.err.println("Download of config failed to execute");
    } catch (JSONException e) {
        e.printStackTrace();
    } 

    cacheStaticData(_context);
}

DownloadJSONTask.java

package com.example.simplegraph;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.os.AsyncTask;

public class DownloadJSONTask extends AsyncTask<String, Integer, JSONObject> {
private HttpClient client = new DefaultHttpClient();
private HttpGet request;
private HttpResponse response;

DownloadJSONTask() {
    super();
}

// tries to grab the data for a JSONObject
@Override
protected JSONObject doInBackground(String... urls) {

    request = new HttpGet(urls[0]);
    try {
        response = client.execute(request);
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream instream = entity.getContent();
            String result = convertStreamToString(instream);
            JSONObject json = new JSONObject(result);
            instream.close();
            return json;
        }
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return null;
}

// converts the InputStream to a string and add nl
private String convertStreamToString(InputStream is) {
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    StringBuilder sb = new StringBuilder();
    String line = null;
    try {
        while ((line = br.readLine()) != null) {
            sb.append(line + "\n");
        }
    } catch (IOException ioe) {
        ioe.printStackTrace();
    } finally {
        try {
            is.close();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
    return sb.toString();
}
}

And HomeActivity.java

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

    new AddStringTask().execute();

}

class AddStringTask extends AsyncTask<Void, String, Void> {
    @Override
    protected Void doInBackground(Void... unused) {

        app = (EconApplication) getApplication();
        getApp().setUp(HomeActivity.this);
        HomeActivity.this.setUpDrawer();
        return (null);
    }

    @Override
    protected void onPostExecute(Void unused) {
        setUpDataDisplay();
        setUpGraphRange();
        createTable();
        createGraph(-1);
    }
}

QUESTION: Why is my code getting stuck on .get()?

JoshDM
  • 4,939
  • 7
  • 43
  • 72
buczek
  • 2,011
  • 7
  • 29
  • 40
  • "stuck" means which logcat-output? – bofredo Aug 08 '13 at 14:53
  • where is this method `get()` and what does it do? – Raghunandan Aug 08 '13 at 14:54
  • @Raghunandan get() is in the first set of code. Just after the try. And it is used to get the JSON. – buczek Aug 08 '13 at 14:58
  • @bofredo there is no logcat-output. Aside from the usual stack allocation and freeing. – buczek Aug 08 '13 at 14:59
  • `get` from where do you have a method called get defined any where in your code?. use an interface to pass the result back to the activity – Raghunandan Aug 08 '13 at 14:59
  • @Raghunandan http://developer.android.com/reference/android/os/AsyncTask.html#get() – buczek Aug 08 '13 at 15:01
  • the method `get()` essentially blocks your Thread and is running the computations of the AsyncTask inside the caller Thread. In your case, you already executed this task (An `AsyncTask` can only run once), so I guess thats the reason – Rafael T Aug 08 '13 at 15:02
  • @RafaelT just to make sure I understand, because I running a thread in my HomeActivity and then calling an AsyncTask inside of this thread, I am then blocking the original thread from completing? – buczek Aug 08 '13 at 15:04
  • @buczek http://stackoverflow.com/questions/9019249/progressdialog-not-shown-when-asynctask-get-called. don't use `get()` . use a interface and make asynctask an inner class of your activity class – Raghunandan Aug 08 '13 at 15:06
  • Did you try accessing the same URL from browser? How long does it take for the sever on that URL to respond? May be the server is taking too long to respond to your request from AsyncTask and that's why it doesn't finish execution till 30 seconds. It is also a good idea to overload of get() and specify a time out. – Sundeep Aug 08 '13 at 15:07
  • @Raghunandan thank you! I think I will have to find a new solution. If you want to post your answer I will accept it. – buczek Aug 08 '13 at 15:08
  • @Sundeep Yes the URL works. The webbrowser is very quick. It takes more than 30 MINUTES, not seconds and still does not finish. – buczek Aug 08 '13 at 15:09
  • @buczek give me time i post a solution using interface – Raghunandan Aug 08 '13 at 15:09
  • @buczek http://stackoverflow.com/questions/16752073/how-do-i-return-a-boolean-from-asynctask. – Raghunandan Aug 08 '13 at 15:20
  • @buczek 30 minutes is very long. Did you try putting a break point inside doInBackground in DownloadJsonTask to see which method call is not returning? – Sundeep Aug 08 '13 at 15:24
  • why do you use an asynctask if you are going to call get on it ? – njzk2 Aug 08 '13 at 15:43

2 Answers2

1

You can greatly simplify everything using my droidQuery library

$.getJSON("http://www.example.com", null, new Function() {//this will run using an AsyncTask, get the JSON, and return either a JSONObject or JSONArray on the UI Thread.
    @Overrde
    public void invoke($ droidQuery, Object... params) {
        if (params[0] instanceof JSONObject) { //it's often ok just to assume a JSONObject, making your first line simply: JSONObject obj = (JSONObject) params[0];
            //JSONObject is returned
            JSONObject json = (JSONObject) params[0];
            //to easily parse this Object, convert it to a map first:
            Map<String, ?> map = $.map(json);
            //then you can just make a call like this:
            if (map.contains("field_currentappversion")) {
                config.currentAppVersion = (String) map.get("field_currentappversion");
            }
        }
        else {
            //JSONArray is returned
            JSONArray json = (JSONArray) params[0];
            //if you got an array, you can easily convert it to an Object[] for parsing:
            Object[] array = $.makeArray(json);
        }
    }
});
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Phil
  • 35,852
  • 23
  • 123
  • 164
1

AsyncTask.get() blocks the caller thread. Use AsyncTask.execute() instead.

public final Result get ()

Added in API level 3

Waits if necessary for the computation to complete, and then retrieves its result.

Returns The computed result.

Drawing from

How do I return a boolean from AsyncTask?

Try the below

  new DownloadJSONTask(ActivityName.this).execute(url);

In your DownloadJSONTask

In the construcotr

    TheInterface listener;
    public DownloadJSONTask(Context context)
{

    listener = (TheInterface) context;

}

Interface

   public interface TheInterface {

    public void theMethod(ArrayList<String> result); // your result type

     }

In your doInbackground return the result. I am assuming its ArrayList of type String. Change the arraylist to what suits your requirement.

In your onPostExecute

   if (listener != null) 
   {
      listener.theMethod(result); // result is the ArrayList<String>
      // result returned in doInbackground 
      // result of doInbackground computation is a parameter to onPostExecute 
   }

In your activity class implement the interface

 public class ActivityName implements DownloadJSONTask.TheInterface

Then

 @Override
 public void theMethod(ArrayList<String> result) { // change the type of result according yo your requirement
 // use the arraylist here
 }

Edit: Alternative

You can makes your asynctask an inner class of your activity class. The result on doInbackground computation is a parameter to onPostExecute. Return result in doInbackground. Update ui in onPostExecute.

Community
  • 1
  • 1
Raghunandan
  • 132,755
  • 26
  • 225
  • 256