Loop AsyncTask class and select Json and save as object in list

I want to connect to an Api that returns me JSON values ​​depending on what I entered as a GET request. This JSON structure is always exactly the same, only the values ​​from these properties are different. All of these JSON values ​​are then built into a list of objects and from there the users in the application will be added.

With help I now have working code that concatenates and reads the values JSON

from HttpEntity

and stores them in new JSONObject

. This object is sent to another function, where the object is split, and then constructed

to Object list

for later use in the application.

This code works . Except that this Api link only shows 50 results, depending on what was entered as the query GET

. If there are more than 50 results, a new page is created that can be accessed by the number at the end of the URL. All of these pages that might exist (not necessarily as his search query) must also be added to the list of objects.

Question . How do I go through an extended class AsyncTask

with a new url to fetch JSON data from?

I note again that this code works for one page, but I cannot figure out how to iterate over all existing pages and add them to the same list of objects.

Let's start with Activity.java

String userSearchRequest = search_activity_data.getString("userSearchRequest");
String URL = "http://www.gw2spidy.com/api/v0.9/json/item-search/" + userSearchRequest + "/";
// example api url:
//http://www.gw2spidy.com/api/v0.9/json/item-search/Iron/0"
//The last number is the page you are viewing, every 50 results a new page is created. With 51 results there will be a page 0 and 1 to access.

AsyncFetch AsyncFetch = new AsyncFetch(this);
AsyncFetch.setOnResponse(this);
AsyncFetch.execute(URL);

      

Here, the URL is passed to the AsyncFetch class for the function doInBackground

as parameters.

public class AsyncFetch extends AsyncTask<String, Void, JSONObject> {

    public AsyncFetch(Context context) {
        this.context = context;
    }

    private Context context;
    private JSONObject jsonObject;
    private onResponse onResponse;

    public void setOnResponse (onResponse onResponse) {
        this.onResponse = onResponse;
    }

    @Override
    protected JSONObject doInBackground(String... params ) { //Incompatible return type
        // TODO Auto-generated method stub

        try {
            HttpGet get = new HttpGet(params[0]);
            HttpClient client = new DefaultHttpClient();
            HttpResponse response = client.execute(get);
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            jsonObject = new JSONObject(result);

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

        return jsonObject;
    }

    @Override
    protected void onPostExecute(JSONObject result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        this.onResponse.onResponse(result);
    }

    public interface onResponse {
        public void onResponse(JSONObject object);
    }


}

      

In onPostExecute

in class, the AsyncFetch

object is then sent back to activity.java

public void onResponse(JSONObject object) {
        Log.i("gw2Log", object.toString());

        apiRootObject resultClass = new apiRootObject();

        try {
            resultClass.setCount(object.getInt("count"));
            resultClass.setPage(object.getInt("page"));
            resultClass.setLast_page(object.getInt("last_page"));
            resultClass.setTotal(object.getInt("total"));
            JSONArray list = new JSONArray(object.getString("results"));

            for (int i = 0; i < resultClass.getCount(); i++) {
                JSONObject resultsObject = list.getJSONObject(i);
                apiResults temp = new apiResults();
                temp.setData_id(resultsObject
                        .getInt("data_id"));
                temp.setName(resultsObject
                        .getString("name"));
                temp.setRarity(resultsObject
                        .getInt("rarity"));
                temp.setRestriction_level(resultsObject
                        .getInt("restriction_level"));
                temp.setImg(resultsObject
                        .getString("img"));
                temp.setType_id(resultsObject
                        .getInt("type_id"));
                temp.setSub_type_id(resultsObject
                        .getInt("sub_type_id"));
                temp.setPrice_last_changed(resultsObject
                        .getString("price_last_changed"));
                temp.setMax_offer_unit_price(resultsObject
                        .getInt("max_offer_unit_price"));
                temp.setMin_sale_unit_price(resultsObject
                        .getInt("min_sale_unit_price"));
                temp.setOffer_availability(resultsObject
                        .getInt("offer_availability"));
                temp.setSale_availability(resultsObject
                        .getInt("sale_availability"));
                temp.setSale_price_change_last_hour(resultsObject
                        .getInt("sale_price_change_last_hour"));
                temp.setOffer_price_change_last_hour(resultsObject
                        .getInt("offer_price_change_last_hour"));
                resultClass.addObject(temp);
            }

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

        for(int i = 0; i < resultClass.count; i++) {
            Log.i("gw2Log", resultClass.getObject(i).name);

        }

    }

      

Now I can access the list resultClass

and loop through all objects and display their properties and values.

How can I make this work for multiple pages with the same JSON structure?

EDIT: I have this code that works in C #. This is the same project, but now in Android java. So the goal is exactly the same, but I cannot get it to work

public static RootObject objFromApi_idToName(string spidyApiUrl, int page){
            RootObject rootObject = null;
            RootObject tempRootObject = null;

            do{
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(spidyApiUrl + "/" + page);

                WebResponse response = request.GetResponse();
                using (Stream responseStream = response.GetResponseStream()){
                    StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
                    var jsonReader = new JsonTextReader(reader);
                    var serializer = new JsonSerializer();
                    tempRootObject = serializer.Deserialize<RootObject>(jsonReader);

                    if (rootObject == null){
                        rootObject = tempRootObject;
                    }
                    else{
                        rootObject.results.AddRange(tempRootObject.results);
                        rootObject.count += tempRootObject.count;
                    }
                }
                page++;
            }

            while (tempRootObject != null && tempRootObject.last_page != tempRootObject.page);
            return rootObject;
        }

      

+3


source to share


2 answers


Well, I don't think it's a good idea what you are trying to do, because you might have OutOfMemoryError

if the amount of server data is too large.

Otherwise, this is my suggestion to load all data:

1) Make two class variables (in your activity), first for the number of pages and the second for your counter:

private static final int PAGES_NUMBER = 38; // i think last page  is 38 in your api
private int mPagesCounter = 0;

      

2) Add JSONObject as a class variable (in your activity) to save your pages:

JSONObject mAllData = new JSONObject();

      



3) Change yours onPostExecute()

to call onResponse()

only when all pages are loaded:

    @Override
        protected void onPostExecute(JSONObject result) {
            super.onPostExecute(result);

            mAllData.put("page"+mPagesCounter, result);// save your current page with "pageX" as key
            mPagesCounter++;

            if(mPagesCounter <= PAGES_NUMBER){// create another task to load next page
                 AsyncFetch AsyncFetch = new AsyncFetch(YourActivity.this);
                 AsyncFetch.setOnResponse(YourActivity.this);
                 AsyncFetch.execute(URL+mPagesCounter);
            } else {// all pages are loaded -> call onResponse() method 
                 this.onResponse.onResponse(mAllData);
            }
        }

      

4) Change the method onResponse()

to handle the new json format.

To create loopback pages, you can do it like this:

    Iterator it = object.keys();
    while (it.hasNext()) {
        String key = (String)it.next();
        try {
            JSONObject jsonPage = object.get(key);// here you get your page
            // do the rest of stuff with the page
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

      

0


source


AsyncTask

, as the name suggests, is a good tool when you are trying to complete a single task asynchronously.

What you are trying to do seems to be Job For ThreadPool

, which is a tool designed to process a job queue using a given number of worker threads (or executors). You can do each task by adding the next task to the queue, or queue the entire batch right away.



This is a very powerful template.

The official example is here (the example is split into several pages, navigation is at the bottom).

0


source







All Articles