1

I have an application that Parses JSON data and displays it to the user in a recycler view. The JSON data I want to parse are in 2 separate arrays. From the office[] array, I want to display the "name". From the officials[] array, I want to display the "name" and "party".

"offices": [
 {
  "name": "President of the United States",
  "party": "Republican
 }
],
"officials": [
 {
  "name": "Donald J. Trump"
 }
]

The data should be parsed and displayed as a single object in the cardview. Here is an example of how it should look. enter image description here

My first approach was to use 2 different for loops to iterate through each array, however this implimentation didn't work, leaving out all the data from the officials array. I got a little closer by using a nested for loop, but there were still displaying incorrectly. Here is my code that handles the JSON parsing and the results.

  //fetch json data from Civic API
private void getData(){
    final ProgressDialog progressDialog = new ProgressDialog(this);
    progressDialog.setMessage("Loading...");
    progressDialog.show();

    StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            progressDialog.dismiss();
            try{
                JSONObject jsonObject = new JSONObject(response);
                //first loop through offices array. Retrieve officeName value
                JSONArray officesArray = jsonObject.getJSONArray("offices");        //One array for offices
                JSONArray officialsArray = jsonObject.getJSONArray("officials");    //one array for officials
                for (int i = 0; i < officesArray.length(); i++){
                    JSONObject jo = officesArray.getJSONObject(i);
                    Reps reps = new Reps(jo.getString("name"));
                    for (int a = 0; a < officialsArray.length(); a++){
                        JSONObject object = officialsArray.getJSONObject(a);        //nested loop
                        Reps rep = new Reps(object.getString("name"),
                                object.getString("party"));
                        repList.add(rep);
                    }
                    repList.add(reps);
                }
                /***
                //loop again this time through officials array
                for (int i = 0;  i < officialsArray.length(); i++){         //Lets see if this loop works*
                    JSONObject object = officialsArray.getJSONObject(i);       //This loop currently doesnt work. Try nested loop?
                    Reps reps = new Reps(object.getString("name"),
                            object.getString("party"));
                    repList.add(reps);
                }***/
                adapter = new RepRvAdapter(repList, getApplicationContext());
                myrv.setAdapter(adapter);
            }catch (JSONException e){
                e.printStackTrace();
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.e("Volley", error.toString());
            progressDialog.dismiss();
        }
    });
    RequestQueue requestQueue = Volley.newRequestQueue(this);
    requestQueue.add(stringRequest);
}

This code is incorrect because it iterates completely through the first array before gathering the the first element in the second array. Once we scroll through all the elements in the first array, we can see the first element of the second array. enter image description here

enter image description here

I understand how my current implimentation is wrong and why the information is being displayed as it is, but I'm not sure of a solution. I was thinking it might be an issue with pushing the data onto the list in the for loop. Or the fact that we have to create two separate Reps objects. What would be the easiest solution for this problem? Let me know if you need to see any more of my code.

My Adapter code as requested:

public class RepRvAdapter extends 
RecyclerView.Adapter<RepRvAdapter.MyViewHolder> {

private Context context;
private List<Reps> repsList;


public RepRvAdapter() {

}



public RepRvAdapter(List<Reps> repList, Context applicationContext) {
    this.repsList = repList;
    this.context = applicationContext;
}


@NonNull
@Override
public RepRvAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    View view;
    LayoutInflater mInflater = LayoutInflater.from(context);
    view = mInflater.inflate(R.layout.card, viewGroup, false);         //Inflate view to card.xml
    return new MyViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull RepRvAdapter.MyViewHolder myViewHolder, int i) {
    myViewHolder.officeName.setText(repsList.get(i).getOfficeName());               //Display these three elements in the card view
    myViewHolder.officialName.setText(repsList.get(i).getOfficialName());
    myViewHolder.party.setText(repsList.get(i).getParty());
}

@Override
public int getItemCount() {
    return repsList.size();
}

public static class MyViewHolder extends RecyclerView.ViewHolder {
    //Variables
    TextView officeName, officialName, party;         //Only the Referendum title and type will be in the recycler view
    public MyViewHolder(View itemView){
        super(itemView);
        officeName = itemView.findViewById(R.id.office_name);
        officialName = itemView.findViewById(R.id.official_name);
        party = itemView.findViewById(R.id.party);
    }
}

}

4
  • post you adapter code Commented Dec 15, 2018 at 10:20
  • I updated with adapter code Commented Dec 15, 2018 at 10:33
  • will the no of entries in both array be same? Commented Dec 15, 2018 at 10:43
  • In our case, yes. In fact the elements in the arrays directly correlate with each other. For example, the first element in the office array is president of the US and the first element of the officials array is Donald Trump, so and so on Commented Dec 15, 2018 at 20:56

1 Answer 1

1

You need to make one constructor that can handle all 3 values in a single object for your Reps class.

Reps(String officeName, String party, String officialName) {
    //assign value from param to each property.
}

Now change your method from activity as below.

try {
            JSONObject jsonObject = new JSONObject(response);
            //first loop through offices array. Retrieve officeName value
            JSONArray officesArray = jsonObject.getJSONArray("offices");        //One array for offices
            JSONArray officialsArray = jsonObject.getJSONArray("officials");    //one array for officials
            for (int i = 0; i < officesArray.length(); i++) {
                JSONObject jsonoffices = officesArray.getJSONObject(i);
                JSONObject jsonofficial = officialsArray.getJSONObject(i);
                Reps reps = new Reps(jsonoffices.getString("name"), jsonoffices.getString("party"), 
                        jsonofficial.getString("name"));
                repList.add(reps);
                adapter = new RepRvAdapter(repList, getApplicationContext());
                myrv.setAdapter(adapter);
            }
        } catch (Exception Ex) {

        }
Sign up to request clarification or add additional context in comments.

2 Comments

This solution worked for me! The only thing was you mixed up the jsonoffices and jsonofficials object when creating the Reps object. I fixed that and it works beautifully. Thanks!
Oh and I also removed the last two lines of code out of the for loop

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.