I’ve received single item from api

Tags: , , ,



I trying to display temperature values that came from the API response in RecyclerView. The thing is my program constantly display just one, first item. I’m not sure where can be the issue, and I feel a bit lost in it.

Part of the api response that I want to display

"hourly": [
{
  "dt": 1607184000,
  "temp": x,
  "feels_like": x,
  "pressure": x,
  "humidity": x,
  "dew_point": x,
  "uvi": x,
  "clouds": x,
  "visibility": x,
  "wind_speed": x,
  "wind_deg": x,
  "pop": x
},
and so on...

Model class

public class ForecastModel {
@SerializedName("hourly")
private List<HourlyForecast> hourlyForecast = null;

public List<HourlyForecast> getHourlyForecast() {
    return hourlyForecast;
}
public class HourlyForecast{
    @SerializedName("dt")
    private int dt;

    public int getDt() {
        return dt;
    }
}

}

Activity class

    public class HourlyForecastActivity extends AppCompatActivity {
    private static final String TAG = "HourlyForecastActivity";
    private List<ForecastModel> mData = new ArrayList<>();
    RecyclerView recyclerView;
    HourlyForecastAdapter adapter;

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

        recyclerView = findViewById(R.id.hourly_recycler_view);
        adapter = new HourlyForecastAdapter();

        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setHasFixedSize(true);
        recyclerView.setAdapter(adapter);
        prepareConnection();
    }
   private void prepareConnection(){
        ForecastViewModel viewModel = new ViewModelProvider(this).get(ForecastViewModel.class);
        viewModel.getData().observe(this, new Observer<ForecastModel>() {
            @Override
            public void onChanged(ForecastModel forecast) {
                if (mData.size() > 0){
                    mData.clear();
                }
                if (forecast != null){
                    mData.addAll(Collections.singleton(forecast));
                    adapter.setData(mData);
                }
            }
        });
   }
}

Adapter class

    public class HourlyForecastAdapter extends RecyclerView.Adapter<HourlyForecastAdapter.HourlyViewHolder> {
    private List<ForecastModel> mHourlyData = new ArrayList<>();

    public void setData(List<ForecastModel> mHourlyData){
        this.mHourlyData = mHourlyData;
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public HourlyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.hourly_items, parent, false);
        return new HourlyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull HourlyViewHolder holder, int position) {
        ForecastModel model = mHourlyData.get(position);
        holder.mTemperature.setText(String.valueOf(model.getHourlyForecast().get(position).getDt()));

    }

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

    public class HourlyViewHolder extends RecyclerView.ViewHolder {
        private TextView mTemperature, mPressure, mHumidity, mWindSpeed, mDescription;
        private ImageView mIcon;

        public HourlyViewHolder(@NonNull View itemView) {
            super(itemView);

            mTemperature = itemView.findViewById(R.id.hourly_temperature);
            mPressure = itemView.findViewById(R.id.hourly_pressure);
            mHumidity = itemView.findViewById(R.id.hourly_humidity);
            mWindSpeed = itemView.findViewById(R.id.hourly_wind_speed);
            mDescription = itemView.findViewById(R.id.hourly_description);
        }
    }
}

Answer

The setData method in your adapter is a bit misleading (naming and variable wise). Looking at your onChanged method in the Activity: a single ForecastModel object is what you are working with. Passing that object to the adapter in setData as a List named mHourlyData is what’s causing the initial confusion. That List will alway be of size 1, causing the problem you are facing.

I recommend changing the onChanged method call to simply do this:

adapter.setData(forecast)

And rename the adapter variable in setData to reflect what your actually are receiving (want to receive):

private List<HourlyForecast> mHourlyForecast = new ArrayList<>();

public void setData(ForecastModel forecast){
    this.mHourlyForecast = forecast.hourlyForecast;
    notifyDataSetChanged();
}

After that, the only thing left to do is update your getItemCount and onBindViewHolder methods accordingly.



Source: stackoverflow