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); } } }
Advertisement
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.