Guy Hoka
Guy Hoka

Reputation: 123

RecyclerView not showing data from JSON

I'm trying to display data gathered from JSON provided by the AirVisual API in a RecyclerView. However, I'm running into a problem where the data from the JSON would not show in the RecyclerView, whereas if I add data to it myself (through an ArrayList), the data would show up in the RecyclerView.

Here is the JSON data I'm parsing from the API:

{
  "status": "success",
  "data": {
    "city": "New York",
    "state": "New York",
    "country": "USA",
    "location": {
      "type": "Point",
      "coordinates": [
        -73.928596,
        40.694401
      ]
    },
    "current": {
      "weather": {
        "ts": "2018-09-12T23:00:00.000Z",
        "hu": 93,
        "ic": "10d",
        "pr": 1024,
        "tp": 23,
        "wd": 102,
        "ws": 2.31
      },
      "pollution": {
        "ts": "2018-09-12T22:00:00.000Z",
        "aqius": 18,
        "mainus": "p2",
        "aqicn": 6,
        "maincn": "p2"
      }
    }
  }
} 

What I'm suspecting is that the data from the JSON did not get added to the ArrayList at all, since logging the size of the ArrayList returned 2, which are the 2 objects I manually added to the list.

For the Station class to store data from the JSON, I used jsonschema2pojo.org to generate the necessary classes for Gson deserialization (not sure if this is the correct/optimal way to use data from the JSON).

Here is the MainActivity.java

public class MainActivity extends AppCompatActivity {
    private static final String url = "http://api.airvisual.com/v2/city?city=New%20York&state=New%20York&country=USA&key={{API_KEY}}";
    private RecyclerView recyclerView;
    private Adapter adapter;

    private List<Station> stationList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        stationList = new ArrayList<>();

        loadRecyclerViewData();

        //Information for these objects are in the code
        //but I decided not to include it in here
        //because these are just for testing
        Station station1 = new Station();
        Station station2 = new Station();

        stationList.add(station1);
        stationList.add(station2);

        adapter = new Adapter(this, stationList);

        recyclerView.setAdapter(adapter);

        //Returns 2 in the console
        Log.d("List Size", "" + stationList.size());

Now here's the loadRecyclerViewData function:

    private void loadRecyclerViewData() {
    RequestQueue requestQueue = Volley.newRequestQueue(this);
    // Request a string response from the provided URL.
    StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    // Using Gson to turn JSON to Java object of Station
                    GsonBuilder gsonBuilder = new GsonBuilder();
                    Gson gson = gsonBuilder.create();
                    Station station = gson.fromJson(response, Station.class);
                    stationList.add(station);
                    Log.d("API RESPONSE", response);
                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.d("VOLLEY ERROR", error.toString());
        }
    });
// Add the request to the RequestQueue.
    requestQueue.add(stringRequest);
}

Adapter class

public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
    private Context context;
    private List<Station> stationList;

    public Adapter(Context context, List<Station> stationList) {
        this.context = context;
        this.stationList = stationList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        View view = layoutInflater.inflate(R.layout.layout_listitem, null);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Station station = stationList.get(position);
        holder.textViewTitle.setText(station.getData().getCity());
        List<Double> coordinates = station.getData().getLocation().getCoordinates();
        String listString = coordinates.stream().map(Object::toString)
                .collect(Collectors.joining(", "));
        holder.textViewShortDesc.setText(listString);
        int aqius = station.getData().getCurrent().getPollution().getAqius();
        holder.textViewRating.setText(aqius + "");
        holder.textViewPrice.setText(rankAQIUS(aqius));
//        holder.imageView.setImageDrawable(context.getResources().getDrawable());
    }

    public String rankAQIUS(int aqius) {
        if (aqius >= 0 && aqius <= 50) {
            return "Good";
        } else if (aqius >= 51 && aqius <= 100) {
            return "Moderate";
        } else if (aqius >= 101 && aqius <= 150) {
            return "Unhealthy for Sensitive Groups";
        } else if (aqius >= 151 && aqius <= 200) {
            return "Unhealthy";
        } else if (aqius >= 201 && aqius <= 300) {
            return "Very Unhealthy";
        } else if (aqius >= 301) {
            return "Hazardous";
        }
        return "ERROR";
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {
        ImageView imageView;
        TextView textViewTitle, textViewShortDesc, textViewRating, textViewPrice;

        public ViewHolder(View itemView) {
            super(itemView);

            imageView = itemView.findViewById(R.id.imageView);
            textViewTitle = itemView.findViewById(R.id.textViewTitle);
            textViewShortDesc = itemView.findViewById(R.id.textViewShortDesc);
            textViewRating = itemView.findViewById(R.id.textViewRating);
            textViewPrice = itemView.findViewById(R.id.textViewPrice);

        }
    }
} 

In the activity_main.xml, I just have a RecyclerView widget

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView> 

Finally for the RecyclerView layout, I just have a CardView in a LinearLayout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="8dp">

            <ImageView
                android:id="@+id/imageView"
                android:layout_width="120dp"
                android:layout_height="90dp"
                android:padding="4dp" />

            <TextView
                android:id="@+id/textViewTitle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:layout_toRightOf="@id/imageView"
                android:text="City, State, Country"
                android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
                android:textColor="#000000" />

            <TextView
                android:id="@+id/textViewShortDesc"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/textViewTitle"
                android:layout_marginLeft="5dp"
                android:layout_marginTop="5dp"
                android:layout_toRightOf="@id/imageView"
                android:text="Longitude, Latitude"
                android:textAppearance="@style/Base.TextAppearance.AppCompat.Small" />

            <TextView
                android:id="@+id/textViewRating"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/textViewShortDesc"
                android:layout_marginLeft="5dp"
                android:layout_marginTop="5dp"
                android:layout_toRightOf="@id/imageView"
                android:background="@color/colorPrimary"
                android:paddingLeft="15dp"
                android:paddingRight="15dp"
                android:text="AQI"
                android:textAppearance="@style/Base.TextAppearance.AppCompat.Small.Inverse"
                android:textStyle="bold" />

            <TextView
                android:id="@+id/textViewPrice"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/textViewRating"
                android:layout_marginLeft="5dp"
                android:layout_marginTop="5dp"
                android:layout_toRightOf="@id/imageView"
                android:text="Risk Level"
                android:textAppearance="@style/Base.TextAppearance.AppCompat.Large"
                android:textStyle="bold" />

        </RelativeLayout>

    </android.support.v7.widget.CardView>

</LinearLayout> 

Here is what the app currently looks like, as you can see there are only 2 items in the RecyclerView, which are the ones I manually added. If the data from the JSON was added, there would be 3 items.

I've tried creating the RecyclerView and Adapter in the loadRecyclerViewData function but ran into errors of "Unknown class: adapter".

Help would be greatly appreciated, thanks!

Bugged RecyclerView screenshot

Upvotes: 0

Views: 958

Answers (1)

Raghu Krishnan R
Raghu Krishnan R

Reputation: 312

  private void loadRecyclerViewData() { RequestQueue requestQueue = Volley.newRequestQueue(this); // Request a string response from the provided URL. StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { // Using Gson to turn JSON to Java object of Station GsonBuilder gsonBuilder = new GsonBuilder(); Gson gson = gsonBuilder.create(); Station station = gson.fromJson(response, Station.class); stationList.add(station);
adapter.notifyDataSetChanged();
Log.d("API RESPONSE", response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.d("VOLLEY ERROR", error.toString()); } }); // Add the request to the RequestQueue. requestQueue.add(stringRequest); }

You have to call notifyDataSetChanged() after adding data to the data set.

Upvotes: 2

Related Questions