niranjan niru niranjan niru - 6 months ago 23
Java Question

Json Array for loop

I'm trying to populate an expandable listview using json data, json parent is displayed properly but the child data is repeating from all the arrays in every child, please refer my code that is how I'm doing the for loop I'm not able to understand where the problem is please help me out friends.

Please see the image attached image

ExpandListdata.java

private void loaditems() {
String url = Constant.commonurlyell + "data_standard_item_ind_new.php?rname=standardtakeaway&id=" + item;
Log.d("ITems", url);
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading...");
progressDialog.show();
JsonArrayRequest arrayRequest = new JsonArrayRequest(Request.Method.GET, url, (String) null, new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
ArrayList<Subitem_base> list = new ArrayList<Subitem_base>();
ArrayList<Subitem_base_child> ch_list = new ArrayList<Subitem_base_child>();
try {
for (int i = 0; i < response.length(); i++) {
JSONObject baseobj = response.getJSONObject(i);
JSONArray itemarry = baseobj.getJSONArray("items");
for (int k = 0; k < itemarry.length(); k++) {
JSONObject itmobj = itemarry.getJSONObject(k);
Subitem_base subitems = new Subitem_base();
subitems.setGroupitemname(itmobj.getString("BaseName"));
JSONArray subitemschildarray = itmobj.getJSONArray("subitems");
for (int j = 0; j < subitemschildarray.length(); j++) {
JSONObject subiteobj = subitemschildarray.getJSONObject(j);
Subitem_base_child subitembase = new Subitem_base_child();
subitembase.setChilditemname(subiteobj.getString("SubItemdesc"));
ch_list.add(subitembase);
}
subitems.setItems(ch_list);
list.add(subitems);
}
}

SubItem_ExpandAdapter subexpand = new SubItem_ExpandAdapter(getApplicationContext(), list);
sec.setAdapter(subexpand);
subexpand.notifyDataSetChanged();
progressDialog.hide();
} catch (JSONException e) {
e.printStackTrace();
}
progressDialog.dismiss();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d("SecondleveError", String.valueOf(error));
}
});
arrayRequest.setRetryPolicy(new DefaultRetryPolicy(50000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
AppController.getInstance().addToRequestQueue(arrayRequest);


The following is my JSON data:

[{
"menu_name": "Beverages",
"items": [{
"id": 1,
"BaseName": "Coca-Cola",
"itemdesc": "",
"subitems": [{
"id": 1,
"SubItemdesc": "0.33L",
"SubItemprice": "0.90"
},
{
"id": 2,
"SubItemdesc": "1.5L",
"SubItemprice": "2.00"
}]
},
{
"id": 2,
"BaseName": "Diet Coca-Cola",
"itemdesc": "",
"subitems": [{
"id": 1,
"SubItemdesc": "0.33L",
"SubItemprice": "0.90"
},
{
"id": 2,
"SubItemdesc": "1.5L",
"SubItemprice": "2.00"
}]
},
{
"id": 3,
"BaseName": "Fanta",
"itemdesc": "",
"subitems": [{
"id": 1,
"SubItemdesc": "0.33L",
"SubItemprice": "0.90"
}]
},
{
"id": 4,
"BaseName": "Tango",
"itemdesc": "",
"subitems": [{
"id": 1,
"SubItemdesc": "0.33L",
"SubItemprice": "0.90"
}]
}]
}]

Answer

Your problem is not in the looping, your problem is that you are forgetting to clear the ch_list every time, so the new items are put in addition to the old items, and if you cleared it, it will not efficiently work as it will be passed by reference so you will have the last element items only, and hence to solve your problem you have to declare a Map which will hold all the ch_list elements for every single item, and then you will use the map by id:

                // here we declare the Map before the "k" for loop        
                Map<Integer, ArrayList<Subitem_base_child>> ch_lists = new HashMap<Integer, ArrayList<Subitem_base_child>>();
                for (int k = 0; k < itemarry.length(); k++) {
                    ch_list = new ArrayList<Subitem_base_child>(); // here is the trick
                    JSONObject itmobj = itemarry.getJSONObject(k);
                    Subitem_base subitems = new Subitem_base();
                    subitems.setGroupitemname(itmobj.getString("BaseName"));
                    JSONArray subitemschildarray = itmobj.getJSONArray("subitems");
                    for (int j = 0; j < subitemschildarray.length(); j++) {
                        JSONObject subiteobj = subitemschildarray.getJSONObject(j);
                        Subitem_base_child subitembase = new Subitem_base_child();
                        subitembase.setChilditemname(subiteobj.getString("SubItemdesc"));
                        ch_list.add(subitembase);
                    }
                    ch_lists.put(k, ch_list);
                    subitems.setItems(ch_lists.get(k));
                    list.add(subitems);
                }

and if the problem is still there, just do the same with list ArrayList.


Explanation:

The problem here happened when you passed the ch_list directly as the ArrayList, in this case each ListView will save the ch_list as a reference variable to the elements, and as the android UI will be executed at the end after running all the loops, it will display the lists and it will find that all lists have the elements that in the list ch_list so it will display the items inside it in all lists, and as you even kept adding values to it or cleared its value each iteration in the loop, so it will display all the items values in the first case and will display only the last item values in the second case, so the problem here has to be solved by saving the values of each list individually without ever changing them, and then when executing it will use these presaved values.

Comments