skip to Main Content

I have an application that parses JSON data and displays it into a recycler view. Each item in the recycler view is an object of the Reps class and is contained within a card layout. The code works fine when I only attempt to parse the string variables.
enter image description here

The moment I attempt to parse the Image URL into the ImageView, the recycler view doesnt display and the activity is blank. I am using Picasso to load the images into the onBinfViewHolder method in my adapter class. Here is the relevant code

Reps:

public class Reps {
private String officeName;
private String officialName;
private String party;
private String photoUrl;

//continue to develop this with other values such as phone, photo, address etc.


public Reps(String officeName, String officialName, String party, String photoUrl) {
    this.officeName = officeName;
    this.officialName = officialName;
    this.party = party;
    this.photoUrl = photoUrl;
}



public Reps(String officeName, String officialName, String party) {
    this.officeName = officeName;
    this.officialName = officialName;
    this.party = party;
}

public Reps(String officeName) {
    this.officeName = officeName;
}

public Reps(String name, String party) {
    this.officialName = name;
    this.party = party;
}


public String getOfficeName() {
    return officeName;
}

public void setOfficeName(String officeName) {
    this.officeName = officeName;
}

public String getOfficialName() {
    return officialName;
}

public void setOfficialName(String officialName) {
    this.officialName = officialName;
}

public String getParty() {
    return party;
}

public void setParty(String party) {
    this.party = party;
}

public String getPhotoUrl() {
    return photoUrl;
}

public void setPhotoUrl(String photoUrl) {
    this.photoUrl = photoUrl;
}

}

RepRvAdapter:

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

private Context context;
private List<Reps> repsList;
RequestOptions option;

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());
    //load image into card view
    Picasso.get()
            .load(repsList.get(i).getPhotoUrl())
            .centerCrop()
            .transform(new CircleTransform(50, 0))
            .fit()
            .into(myViewHolder.photoUrl);
}

@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
    ImageView photoUrl;
    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);
        photoUrl = itemView.findViewById(R.id.photo_url);
    }
}

}

Method that parses JSON data:

 //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 jsonOffices = officesArray.getJSONObject(i);
                    JSONObject jsonOfficials = officialsArray.getJSONObject(i);
                    Reps reps = new Reps (jsonOfficials.getString("name"),
                            jsonOfficials.getString("party"),
                            //jsonOfficials.getString("photoUrl")
                            jsonOffices.getString("name"));
                    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);
}

Right now, I have the line of code that parses the image URL commented out. Once the line is uncommented, the activity no longer displays. How can I get the Image url to be parsed and displayed in the ImageView? I think it might be an issue with the JSON data. In the JSON array, not all photoUrl fields are set. The API may not return image data for every representative in the array, whereas the party, name and office fields always have values. Can this be what stops the recycler view from displaying? Here is a relevant chunk of JSON data:

"officials": [
  {
   "name": "Donald J. Trump",
   "address": [
    {
     "line1": "The White House",
     "line2": "1600 Pennsylvania Avenue NW",
     "city": "Washington",
     "state": "DC",
     "zip": "20500"
    }
   ],
   "party": "Republican",
   "phones": [
    "(202) 456-1111"
   ],    
    "photoUrl":"https://www.whitehouse.gov/sites/whitehouse.gov/files/images/45/PE%20Color.jpg",
   "channels": [
    {
     "type": "GooglePlus",
     "id": "+whitehouse"
    },
    {
     "type": "Facebook",
     "id": "whitehouse"
    },
    {
     "type": "Twitter",
     "id": "potus"
    },
    {
     "type": "YouTube",
     "id": "whitehouse"
    }
   ]
  },
  {
   "name": "Mike Pence",
   "address": [
    {
     "line1": "The White House",
     "line2": "1600 Pennsylvania Avenue NW",
     "city": "Washington",
     "state": "DC",
     "zip": "20500"
    }
   ],
   "party": "Republican",
   "phones": [
    "(202) 456-1111"
   ],
   "photoUrl":"https://www.whitehouse.gov/sites/whitehouse.gov/files/images/45/VPE%20Color.jpg",
   "channels": [
    {
     "type": "GooglePlus",
     "id": "+whitehouse"
    },
    {
     "type": "Facebook",
     "id": "whitehouse"
    },
    {
     "type": "Twitter",
     "id": "VP"
    }
   ]
  },
  {
   "name": "Dianne Feinstein",
   "address": [
    {
     "line1": "331 Hart Senate Office Building",
     "city": "Washington",
     "state": "DC",
     "zip": "20510"
    }
   ],
   "party": "Democratic",
   "phones": [
    "(202) 224-3841"
   ],
   "photoUrl": "http://bioguide.congress.gov/bioguide/photo/F/F000062.jpg",
   "channels": [
    {
     "type": "Facebook",
     "id": "SenatorFeinstein"
    },
    {
     "type": "Twitter",
     "id": "SenFeinstein"
    },
    {
     "type": "YouTube",
     "id": "SenatorFeinstein"
    }
   ]
  },
  {
   "name": "Kamala D. Harris",
   "address": [
    {
     "line1": "112 Hart Senate Office Building",
     "city": "Washington",
     "state": "DC",
     "zip": "20510"
    }
   ],
   "party": "Democratic",
   "phones": [
    "(202) 224-3553"
   ],
   "channels": [
    {
     "type": "Twitter",
     "id": "KamalaHarris"
    },
    {
     "type": "YouTube",
     "id": "UC0XBsJpPhOLg0k4x9ZwrWzw"
    }
   ]

As you can see, All representative have a name, party and office, but not all representatives have an image URL. The logcat returns this in regards to it.
enter image description here

I am willing to try different libraries. Let me know if you need to see any more code. Thanks for the help!

I added the following conditional to my jsonParse method to account for objects with no photoUrl field.

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 jsonOfficials = officialsArray.getJSONObject(i);
                   if(jsonOfficials.has("photoUrl")){
                        Reps reps = new Reps (jsonOfficials.getString("name"),
                                jsonOfficials.getString("party"),
                                jsonOfficials.getString("photoUrl"),
                                jsonOffices.getString("name"));
                        repList.add(reps);
                    }else{
                       Reps reps = new Reps(jsonOfficials.getString("name"),
                               jsonOfficials.getString("party"),
                               jsonOffices.getString("name"));
                       repList.add(reps);
                   }
                }
                adapter = new RepRvAdapter(repList, getApplicationContext());
                myrv.setAdapter(adapter);

With this code, the recycler view displays, but the image URL string is displayed in the officeName textview instead of an image in the ImageView.
enter image description here

Since the last official doesnt have an image available, their data is displayed correctly.

2

Answers


  1. There is a mistake in the JSON Response. Try this

        [{
            "name": "Donald J. Trump",
            "address": [{
                "line1": "The White House",
                "line2": "1600 Pennsylvania Avenue NW",
                "city": "Washington",
                "state": "DC",
                "zip": "20500"
            }],
            "party": "Republican",
            "phones": [
                "(202) 456-1111"
            ],
            "photoUrl": "https://www.whitehouse.gov/sites/whitehouse.gov/files/images/45/PE%20Color.jpg",
            "channels": [{
                    "type": "GooglePlus",
                    "id": "+whitehouse"
                },
                {
                    "type": "Facebook",
                    "id": "whitehouse"
                },
                {
                    "type": "Twitter",
                    "id": "potus"
                },
                {
                    "type": "YouTube",
                    "id": "whitehouse"
                }
            ]
        },
    {
       "name": "Mike Pence",
       "address": [
        {
         "line1": "The White House",
         "line2": "1600 Pennsylvania Avenue NW",
         "city": "Washington",
         "state": "DC",
         "zip": "20500"
        }
       ],
       "party": "Republican",
       "phones": [
        "(202) 456-1111"
       ],
       "photoUrl":"https://www.whitehouse.gov/sites/whitehouse.gov/files/images/45/VPE%20Color.jpg",
       "channels": [
        {
         "type": "GooglePlus",
         "id": "+whitehouse"
        },
        {
         "type": "Facebook",
         "id": "whitehouse"
        },
        {
         "type": "Twitter",
         "id": "VP"
        }
       ]
      },
      {
       "name": "Dianne Feinstein",
       "address": [
        {
         "line1": "331 Hart Senate Office Building",
         "city": "Washington",
         "state": "DC",
         "zip": "20510"
        }
       ],
       "party": "Democratic",
       "phones": [
        "(202) 224-3841"
       ],
       "photoUrl": "http://bioguide.congress.gov/bioguide/photo/F/F000062.jpg",
       "channels": [
        {
         "type": "Facebook",
         "id": "SenatorFeinstein"
        },
        {
         "type": "Twitter",
         "id": "SenFeinstein"
        },
        {
         "type": "YouTube",
         "id": "SenatorFeinstein"
        }
       ]
      },
      {
       "name": "Kamala D. Harris",
       "address": [
        {
         "line1": "112 Hart Senate Office Building",
         "city": "Washington",
         "state": "DC",
         "zip": "20510"
        }
       ],
       "party": "Democratic",
       "phones": [
        "(202) 224-3553"
       ],
       "channels": [
        {
         "type": "Twitter",
         "id": "KamalaHarris"
        },
        {
         "type": "YouTube",
         "id": "UC0XBsJpPhOLg0k4x9ZwrWzw"
        }
    ]
    }
    ]
    
    Login or Signup to reply.
  2. Problem#1: A JSON Exception Occurred When you try to parse “photoUrl”, cause there is no field exist named “photoUrl” in last officials object.

    {
          "name": "Kamala D. Harris",
          "address": [
            {
              "line1": "112 Hart Senate Office Building",
              "city": "Washington",
              "state": "DC",
              "zip": "20510"
            }
          ],
          "party": "Democratic",
          "phones": [
            "(202) 224-3553"
          ],
          "channels": [
            {
              "type": "Twitter",
              "id": "KamalaHarris"
            },
            {
              "type": "YouTube",
              "id": "UC0XBsJpPhOLg0k4x9ZwrWzw"
            }
          ]
        }
    

    Solution#1: Just put the code inside a condition like:

    String photoUrl = "";
    if (jsonOfficials.has("photoUrl")) {
       photoUrl = jsonOfficials.getString("photoUrl");
    }
    

    Problem#2: please check your “Reps” class 1st constructor. Here, u get the “photoUrl” feild as 4th parameter, but when u create an object of “Reps” class, u pass “photoUrl” feild as 3rd parameter.

    Solution#2:

    Reps reps = new Reps (jsonOfficials.getString("name"),
        jsonOfficials.getString("party"),
        jsonOffices.getString("name"),
        jsonOfficials.getString("photoUrl"));
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search